Spring AOP 源码分析 详解

Spring AOP HelloWorld (注解版)

1、导入依赖aop依赖

<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-aspectsartifactId>
    <version>4.3.12.RELEASEversion>
dependency>

2、 定义业务逻辑类 ;在业务逻辑执行的时候进行日志打印(方法执行之前,方法运行结束,异常,返回 …)

3、日志切面类:切面类里面的方法需要动态的感知业务类方法运行到哪一步了

4、通知方法

  • 前置通知(@Before):在目标方法执行之前执行
  • 后置通知(@After):在目标方法运行结束之后执行
  • 返回通知(@AfterReturning):在目标方法正常返回之后运行
  • 异常通知(@AfterThrowing):在目标方法运行出现异常以后运行
  • 环绕通知(@Around):动态代理,手动推进方法运行

5、 给切面类的目标方法标注运行时机(通知注解)
6、将切面类和目标类都加入到容器中
7、必须告诉spring哪个类是切面类(给切面类加上注解:@Aspect)
8、给配置 类加上@EnableAspectJAutoProxy(开启基于注解 aop模式)

代码示例
业务类

public class MathCalculator {

    public int div(int i, int j) {
        return i/j;
    }
}

日志切面类

/**
 * 切面类
 */
@Aspect
public class LogAspects {

    @Pointcut("execution(public int com.fyj.spring.annotation.aop.MathCalculator.*(..))")
    public void pointCut() {}

    @Before("pointCut()")
    public void logStart(JoinPoint joinPoint) {
        String name = joinPoint.getSignature().getName();
        List<Object> list = Arrays.asList(joinPoint.getArgs());
        System.out.println(name + "运行开始。。。参数列表是:{"+list+"}");
    }

    @After("pointCut()")
    public void logEnd(JoinPoint joinPoint) {
        String name = joinPoint.getSignature().getName();
        List<Object> list = Arrays.asList(joinPoint.getArgs());
        System.out.println(name + "除法运行结束 。。。参数列表是:{"+list+"}");
    }

    @AfterReturning(value = "pointCut()", returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result) {

        System.out.println(joinPoint.getSignature().getName() + "除法正常返回 。。。运行结果:{"+result+ "}");
    }

    @AfterThrowing(value = "pointCut()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception) {
        System.out.println(joinPoint.getSignature().getName() + "异常 。。。异常信息:{"+exception.getMessage()+"}");
    }
}

配置类

@Configuration
@EnableAspectJAutoProxy
public class MyConfigration {

    @Bean
    public MathCalculator mathCalculator () {
        return new MathCalculator();
    }

    @Bean
    public LogAspects logAspects(){
        return new LogAspects();
    }
}

测试类

public class MyTest {

    @Test
    public void test01 () {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfigration.class);
        MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
        mathCalculator.div(1, 1);
//        mathCalculator.div(1, 0);
    }
}

运行结果:
Spring AOP 源码分析 详解_第1张图片

AOP 源码分析

分析Spring AOP原理从@EnableAspectJAutoProxy 开始
@EnableAspectJAutoProxy 导入了 AspectJAutoProxyRegistrar 这个类
在这里插入图片描述

1. @EnableAspectJAutoProxy 是什么?

@Import(AspectJAutoProxyRegistrar.class),给容器中导入AspectJAutoProxyRegistrar
- 利用AspectJAutoProxyRegistrar自定义给容器中注册bean;BeanDefinetion
internalAutoProxyCreator=AnnotationAwareAspectJAutoProxyCreator
第一步就是给容器中注册一个AnnotationAwareAspectJAutoProxyCreator

2. 先创建AnnotationAwareAspectJAutoProxyCreator

在IOC容器的创建过程中,会先实例化 BeanPostProcessors,而 AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessors ,继承树如下:

AnnotationAwareAspectJAutoProxyCreator 继承树如下:
> AnnotationAwareAspectJAutoProxyCreator
		 ->AspectJAwareAdvisorAutoProxyCreator
		  	->AbstractAdvisorAutoProxyCreator
				->AbstractAutoProxyCreator
						implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
					关注后置处理器(在bean初始化完成前后做事情)、自动装配BeanFactory
  AbstractAutoProxyCreator.setBeanFactory()

AbstractAutoProxyCreator.有后置处理器的逻辑;
AbstractAdvisorAutoProxyCreator.setBeanFactory()-》initBeanFactory()
AnnotationAwareAspectJAutoProxyCreator.initBeanFactory()

IOC容器中BeanPostProcessors 创建过程
即 AnnotationAwareAspectJAutoProxyCreator 的创建,
AnnotationAwareAspectJAutoProxyCreator是一个BeanPostProcessors
Spring AOP 源码分析 详解_第2张图片
以上是创建和注册AnnotationAwareAspectJAutoProxyCreator的过程

3. 再创建剩下的单实例bean(即业务类,切面类),完成BeanFactory初始化工作

  1. 该步骤的关键点是在 实例化bean的时候AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前会有一个拦截,InstantiationAwareBeanPostProcessor,会调用postProcessBeforeInstantiation()
  2. AnnotationAwareAspectJAutoProxyCreator 会在任何bean创建之前先尝试返回bean的实例(创建一个代理对象)

Spring AOP 源码分析 详解_第3张图片

4. AnnotationAwareAspectJAutoProxyCreator的作用

  1. 每一个bean创建之前,调用AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation();方法
    Spring AOP 源码分析 详解_第4张图片

  2. 创建代理对象 ,调用AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法
    Spring AOP 源码分析 详解_第5张图片

  3. 目标方法执行
    Spring AOP 源码分析 详解_第6张图片

调用链如图:
Spring AOP 源码分析 详解_第7张图片

AOP源码分析总结

Spring AOP 源码分析 详解_第8张图片

你可能感兴趣的:(Spring,注解驱动)