回顾
首先回顾:
Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别
我们得知 JDK动态代理两要素:Proxy+InvocationHandler CGLB动态代理两要素:Enhancer + MethodInterceptor(Callback)
springAOP底层是通过动态代理和CGLB代理实现的。也就是spring最终的落脚点还应该是在Proxy+InvocationHandler 或者Enhancer + MethodInterceptor上。
带着这个期待我们看看spring是如何组织AOP的,并在动态代理之上建立一个AOP体系的。
概念的理解:
- 通知: 通知可以理解增强器, 就是做的额外工作.
- 连接点: 可以允许切面插入的点, 这个点可以是方法调用时, 抛出异常时等.
- 切点: 并不是所有的连接点都需要被切面插入, 切点就是定义哪些连接点可以插入切面.
总结为:从所有连接点中选出部分连接点, 进行拦截,执行额外操作。
组件的理解:
AOP最早由AOP联盟的组织提出的,制定了一套规范.Spring将AOP思想引入到框架中,必须遵守AOP联盟的规范.
注意:各种组件非常之多. 我只把自认为涉及到主线理解的组件列出
AOP联盟规范定义组件
通知(增强器): 不要纠结于太多. 就统一理解为拦截器或者增强器。
spring定义组件
1.Pointcut:定义哪些连接点可以插入切面。提供ClassFilter 与MethodMatcher两种匹配器,匹配连接点。
2.Advisor : 包装Advice和Pointcut .语义: 在哪里拦截, 插入什么样的增强器(在哪里做什么)Advisor=Advice+Pointcut分为
- IntroductionAdvisor: 引介增强,在不修改某个类的情况下, 让其具备某接口的功能。
- PointcutAdvisor: 与切点有关的Advisor
3.TargetSource: 对目标对象的封装。
4.Advised接口 : 包装 Advisor 与 TargetSource。 实现类AdvisedSupport:从其两个属性上,真切看出其封装了 Advisor 与 TargetSource
- TargetSource targetSource = EMPTY_TARGET_SOURCE; 表示目标对象
- private List advisors = new ArrayList(); 存储Advisor
5.AopProxy:AOP代理对象
- 分JDK代理(JdkDynamicAopProxy)
- Cglib代理(CglibAopProxy)
JdkDynamicAopProxy与CglibAopProxy都实现了AopProxy的getProxy()方法,用于返回真正的代理对象。
6.AopProxyFactory:AOP代理策略工厂类。根据条件选择使用JDK还是Cglib的方式来创建代理对象
7.ProxyCreatorSupport: 从其语义上理解,对创建代理对象的支持。我们从其继承关系上看看他是如何提供支持的。
- ProxyConfig: 提供aop配置属性。
- AdvisedSupport:继承ProxyConfig,实现了Advised接口。封装通知(Advise)和TargetSource,并提供对他们的操作
- ProxyCreatorSupport: 包含AopProxyFactory,AopProxyFactory策略工厂提供对JdkDynamicAopProxy与CglibAopProxy的创建
8.AbstractAutoProxyCreator: 从其继承关系。我们分析下这个组件。
- 首先他是一个(BeanPostProcessor)InstantiationAwareBeanPostProcessor 所以他会在spring的Bean生产线createBean()过程中被执行。在BeanDefinition创建Bean的过程中进行拦截,根据要求创建出代理对象。
- Aware: 可以获取到BeanFactory仓库, 与BeanClassLoader加载器。
- ProxyCreatorSupport,继承了创建代理的功能。
关于BeanPostProcessor与InstantiationAwareBeanPostProcessor的理解,还是深刻理解Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别。
小结:
如果总结下组件之间的关系:
开发人员定义切面信息--》spring解析出Advice,切点等配置信息--》AopProxyFactory根据配置创建代理对象--》代理方法执行。
这也是springAOP大部分工作内容。
笼统来看:
- 《1》定义的解析:
- 《2》代理的创建:
- 《3》代理的执行:
下面我们重点看看定义的解析与代理的创建。
代理的生成过程:
代理的执行过程: 我们还是以springboot环境下的AOP实现来讲讲AOP的过程.
1.配置AOP的扩展器,拦截BeanDefiniiton创建Bean的过程:AnnotationAwareAspectJAutoProxyCreator:
首先配置AOP环境
@EnableAspectJAutoProxy注解上的@Import(AspectJAutoProxyRegistrar.class)引入AspectJAutoProxyRegistrar类.AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口. 所以其registerBeanDefinitions()会有一些注入BeanDefiniiton的操作 . registerBeanDefinitions()方法会向仓库中注入一个AnnotationAwareAspectJAutoProxyCreator.
@Override public void registerBeanDefinitions( AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { //注入AnnotationAwareAspectJAutoProxyCreator扩展器 AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class); if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } if (enableAspectJAutoProxy.getBoolean("exposeProxy")) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } }
AnnotationAwareAspectJAutoProxyCreator 间接继承了AOP扩展工具AbstractAutoProxyCreator, 是一个BeanPostProcessor。
AbstractAutoProxyCreator:
- 是一个BeanPostProcessor,可以拦截Bean创建过程
- 继承了ProxyCreatorSupport具有代理类的创建能力。
这样:AOP环境有了。
2.拦截生产过程,创建AOP对象:
createBean()生产线在创建Bean的过程中. 会执行所有的BeanPostProcessor. AnnotationAwareAspectJAutoProxyCreator(AbstractAutoProxyCreator)作为一个BeanPostProcessor也在此时执行.
在Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别讲过. 实现了InstantiationAwareBeanPostProcessor接口的BeanPostProcessor的会有5个方法伴随Bean创建过程且执行顺序。postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessPropertyValues-->postProcessBeforeInitialization()-->postProcessAfterInitialization()
过程:
(2.1)首先执行的是postProcessBeforeInstantiation 实例化前置处理方法
@Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { return null; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; }
主要分为两部分: (2.1.1)先判断是否应该代理
- isInfrastructureClass(beanClass)如果是AOP基础设施类, 不代理。指的是Advice、Pointcut、Advisor等AOP相关定义类不应该创建代理
- shouldSkip()应该跳过的类,不代理。判断的依据:默认是都不跳过的. 子类可能重写其判断依据.AnnotationAwareAspectJAutoProxyCreator的父类AnnotationAwareAspectJAutoProxyCreator重写了shouldSkip方法(《1》并伴随切面定义的解析)。
重点看看shouldSkip()
/* 1.首先查找适于当前Bean的Advisor .通findCandidateAdvisors()去查找 findCandidateAdvisors()会经过两个渠道获取Advisors. > BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans():是从仓库中找实现了Advisor类的Advisor > BeanFactoryAspectJAdvisorsBuilder.buildAspectJAdvisors()会从仓库中取出@Aspect注解的切面类,解析出Advisor 重点说一下其中buildAspectJAdvisors >遍历BeanFactory仓库中的BeanDefinition,根据其类型判断其是否是isAspect(): 判断条件是类是否被@Aspect注释,并且没有被aspectj编译过 >如果是, 根据当前BeanDefinition创建一个(AspectJAdvisorFactory)BeanFactoryAspectInstanceFactory工厂对象. >使用AspectJAdvisorFactory 工厂创建List<Advisor> >上文已经说过Advisor=Advice+Pointcut, Advice 就是对通知的封装(@Before...), Pointcut 是对切点的封装. 小结:这次知道我们定义一个切面类, 被解析什么样子了吧 2.判断找到的CandidateAdvisors中有没有当前BeanDefinition,有的话就跳过。 */ @Override protected boolean shouldSkip(Class<?> beanClass, String beanName) { // TODO: Consider optimization by caching the list of the aspect names List<Advisor> candidateAdvisors = findCandidateAdvisors(); for (Advisor advisor : candidateAdvisors) { if (advisor instanceof AspectJPointcutAdvisor) { if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) { return true; } } } return super.shouldSkip(beanClass, beanName); }
(2.1.2) 判断是否有自定义的 TargetSource。 如果有自定义TargetSource ,将当前beanName放入targetSourcedBeans缓存中,直接走创建代理的分支,不会走createBean去创建Bean,这里就是给一个机会。 关于自定义TargetSource这个分支暂时不讲。
if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } }
总结postProcessBeforeInstantiation工作内容:
- 解析切面定义
- 提供一个机会直接返回代理对象,不走createBean()流水线。自定义TargetSource
(2.2)postProcessAfterInstantiation
- return true ;
(2.3)postProcessBeforeInitialization
- 返回Bean没有做处理
(2.4)postProcessAfterInitialization() (敲黑板,重点)