Spring注解驱动开发之AOP

AOP概念:

  切入点(pointcut):需要增强的目标方法。

  连接点(joinpoint):方法连接点,方法有关的前前后后都是连接点。即切点的全集。

  通知(advice):某个方法在执行前或执行后要完成的工作

  切面(aspect):切点和通知共同定义了切面的全部功能——它是什么,在何时何处完成其功能,切面就是横切关注点的抽象。

  动态代理:Spring AOP使用动态代理,所谓动态代理即AOP框架不会修改原来的对象,而是在需要的时候重新生成一个代理对象,这个代理对象包含了目标对象的全部发放,并且在指定的切点做了处理,而且最终还是回调原对象的方法。  

  动态代理有两种方式,JDK动态代理和CGLIB动态代理。

  JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口,其核心是InvocationHandler接口和Proxy类。 

  如果目标类没有实现接口,那就要选择使用CGLIB来动态代理目标类。CGLIB是通过继承的方式做的动态代理,因此,如果某个类被标记为final,那么它是无法使用CGLIB做动态代理。CGLIB会使生成的代理类继承当前的对象,并在代理类中对代理方法进行强化处理(前置处理、后置处理等)。

 

1、AOP基本搭建:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>4.3.8.RELEASE</version>
</dependency>  
@Configuration
@ComponentScan(value = "com.aop.test")
@EnableAspectJAutoProxy
public class ConfigAOP {
}

  

@Aspect
@Component
public class LogAspects {
    @Pointcut("execution( public int com.aop.test.MathCaculator.div(..))")
    public void pointcut(){
    }
    @Before("pointcut()")
    public void logstart(JoinPoint joinPoint){
        System.out.println("@Before      aop方法运行开始。。。。获取方法名:"+joinPoint.getSignature().getName()+
        "获取方法的参数列表:" +Arrays.asList(joinPoint.getArgs()));
    }
    @After("pointcut()")
    public void logEnd(){
        System.out.println("@After:   aop方法运算结束");
    }
    @AfterReturning("pointcut()")
    public void logReturn(){
        System.out.println("@AfterReturning:   aop方法返回");
    }
    @AfterThrowing(value = "pointcut()",throwing = "exception")
    public void logException(Exception exception){
        System.out.println("@AfterThrowing    打印aop方法异常信息:");
    }
}

  

@Component
public class MathCaculator {
    public int div(int a,int b) throws Exception {
        System.out.println("除法的方法主体");
        return a/b;
    }
}

  

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(ConfigAOP.class);
        System.out.println("容器初始化成功");
        MathCaculator MathCaculator = annotationConfigApplicationContext.getBean(MathCaculator.class);
        MathCaculator.div(1,0);
        annotationConfigApplicationContext.close();
    }
}

2、AOP的简单注解:

  在配置类中:@EnableAspectJAutoProxy(开启基于注解的aop模式)

  切面类:@Aspect(告诉Spring哪个是切面类,切面类也要要注解@Component才能将切面类加入到注解中)

3、AOP源码解析(aop原理即:给容器中注册了哪些组件,这些组件什么时候工作,以及组件功能是什么):

  @EnableAspectJAutoProxy 开始源码分析:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
}
  • 在这里可以看到导入了一个组件AspectJAutoProxyRegistrar.class,利用它,可以自定义注册bean。

      org.springframework.aop.config.internalAutoProxyCreator  -> org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

        给容器中注册一个类型为AnnotationAwareAspectJAutoProxyCreator名字为internalAutoProxyCreator的bean 。

  • 给容器注入AnnotationAwareAspectJAutoProxyCreator的作用:
         该类实现了接口SmartInstantiationAwareBeanPostProcessor和BeanFactoryAware,其中BeanPostProcessor接口关注在bean初始化前后做的事情,BeanFactoryAware接口关注自动装配BeanFactory

    

 流程:

  1)传入配置类,创建ioc容器。

    AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(ConfigAOP.class);

  2)注册配置类,调用refresh()刷新容器

   

  3)registerBeanPostProcessors(beanFactory); 注册bean的后置处理器来方便拦截bean的创建

   

原文地址:https://www.cnblogs.com/yaohuiqin/p/10114920.html