文章目录
-
-
- Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser
-
- 1.获取增强方法
-
Step 1:初始化解析器 AspectJAutoProxyBeanDefinitionParser
AspectJAutoProxyBeanDefinitionParser:遇到 aspectj-autoproxy 注解时,用该解析器进行解析,即:
<!-- 声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。-->
<aop:aspectj-autoproxy/>
###Step 2:调用AspectJAutoProxyBeanDefinitionParser的parse函数注册AnnotationAwareAspectJAutoProxyCreator类(代理生成器,在解析配置文件时候)
- 需要考虑到自定义代理生成器与当时不一致,需要根据优先级来决定使用哪一个
- 自定义代理生成器常用的有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类
- 获取增强器等解析操作是Spring解析配置文件的时候,此时获取所有增强器并创建代理
- 调用Bean方法的时候调用代理的invoke方法
AOP有三种植入切面的方法:
- 其一是编译期织入,这要求使用特殊的Java编译器,AspectJ是其中的代表者;
- 其二是类装载期织入,而这要求使用特殊的类装载器,AspectJ和AspectWerkz是其中的代表者;
- 其三为动态代理织入,在运行期为目标类添加增强生成子类的方式,Spring AOP采用动态代理织入切面。