天天看点

Spring AOP解析过程

文章目录

      • Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser
        • 1.获取增强方法

Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser

AspectJAutoProxyBeanDefinitionParser:遇到 aspectj-autoproxy 注解时,用该解析器进行解析,即:

<!-- 声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。-->
<aop:aspectj-autoproxy/> 
           

###Step 2:调用AspectJAutoProxyBeanDefinitionParser的parse函数注册AnnotationAwareAspectJAutoProxyCreator类(代理生成器,在解析配置文件时候)

  1. 需要考虑到自定义代理生成器与当时不一致,需要根据优先级来决定使用哪一个
  2. 自定义代理生成器常用的有DefaultAdvisorAutoProxyCreator和BeanNameAutoProxyCreator,其中DefaultAdvisorAutoProxyCreator 比较暴力 ,会把容器内所有的切面向所有的目标对象织入,而且切面只能是顾问的形式。而BeanNameAutoProxyCreator比较友好,可以让我们有选择性的对目标对象和切面进行织入的操作,而且切面可以是顾问或者通知的形式。

###Step 3:由于AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor接口,则会在加载该Bean过程中会调用后处理方法(AbstractAutoProxyCreator类中)

1.获取增强方法

第一步:获取所有的增强器

(1)获取所有的BeanName,其中包括父类的(递归查找)

(2)遍历所有BeanName,找出声明为AspectJ注解的类

(3)若切面类是AspectJ的Singleton实例化模型,则表示切面只有一个实例,则创建BeanFactoryAspectInstanceFactory工厂,否则创建PrototypeAspectInstanceFactory工厂(PrototypeAspectInstanceFactory继承了BeanFactoryAspectInstanceFactory工厂)

(4)对每个AspectJ注解的类来根据工厂获取增强器Advisor(顾问)列表

  • Step 1:针对类中每个方法获取增强器
  • Step 2:增加同步实例化增强器(P185)
  • Step 3:获取DeclareParents注解(使用DeclareParentsAdvisor进行封装)

获取增强器Advisor列表过程(针对每个方法获取增强器的流程)

(1)对aspectClass每个方法获取该方法上的切点信息(即Pointcut,查找Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class),并封装在AspectJExpressionPointcut类中

(2)根据找到的每个切点信息生成增强,所有的增强由Advisor的实现类InstantiationModelAwarePointcutAdvisorImpl统一封装。

(3)在封装类InstantiationModelAwarePointcutAdvisorImpl中调用this.aspectJAdvisorFactory的getAdvice的方法,该方法根据不同的注解类型封装不同的增强器

  • AtBefore注解(@Before)—>创建AspectJMethodBeforeAdvice:MethodBeforeAdviceInterceptor
  • AtAfter注解(@After)—>创建AspectJAfterAdvice:由于AspectJAfterAdvice实现了拦截器,直接调用
  • AtAfterReturning注解(@AfterReturning)—->创建AspectJAfterReturningAdvice
  • AtAfterThrowing注解(@AfterThrowing)—>创建AspectJAfterThrowingAdvice
  • AtAround注解(@Around)—>创建AspectJAroundAdvice

第二步:寻找匹配的增强器

检查目标类是否符合切点表达式

####2.创建代理

第一步:创建ProxyFactory来进行代理类的创建与处理

第二步:若设置proxyTarClass为false,则添加代理接口

第三步:将拦截器封装成增强器

第四步:创建代理

a. 条件

若proxyTargetClass属性为true,或者存在代理接口时使用CGLIB代理,否则使用JDK动态代理

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}
           

b.JdkDynamicAopProxy类(实现了InvocationHandler接口)中的invoke方法

创建一个拦截器链,并一个个执行(如前面创建的增强器就此时执行)

c.CglibAopProxy类

  1. 获取增强器等解析操作是Spring解析配置文件的时候,此时获取所有增强器并创建代理
  2. 调用Bean方法的时候调用代理的invoke方法
AOP有三种植入切面的方法:
  • 其一是编译期织入,这要求使用特殊的Java编译器,AspectJ是其中的代表者;
  • 其二是类装载期织入,而这要求使用特殊的类装载器,AspectJ和AspectWerkz是其中的代表者;
  • 其三为动态代理织入,在运行期为目标类添加增强生成子类的方式,Spring AOP采用动态代理织入切面。