背景:
很多小伙伴看Spring aop的源码有没有觉得 、spring容器中比如各种通知器是什么时候加载进容器的。最后在实例话这个通知器的时候一直在“套娃模式”、为什么会有那么多的套娃呢?这里特别容易蒙。这里记录一下。
Spring Aop配置:
如果你是Spring AOP的设计人员、你会提前准备哪些东西?
1、Aop的核心就是在目标方法执行某些时机 执行某些统一的逻辑 对于java而言就是,这些逻辑就要写在一个类里、这样的切面类就叫Aspect(用户手动编写)
2、既然是某些时机做Aspect中某些逻辑操作,那么自然而然就会想到生成代理类、在代理类中调用目标类。
3、Spring工程可以有N多类、如何确认哪些类需要代理? Spring包装成PointCut. 即:要提前准备AspectJExpressionPointcut. (根据用户配置 spring内置)
4、上面提到 某些时机执行某些逻辑操作 对于java而言就要封装成具体的对象。Spring用通知器Advisor来封装这些对象、所以就要提前准备Advisor。 但是这就是初看Spring Aop源码蒙的地方、初始化Advisor一直在“套娃”。 在实例话Advisor的时候还需要初始化构造方法的三个参数即:MethodLocatingFactoryBean、pointcut、SimpleBeanFactoryAwareAspectInstanceFactory 。所以在实例化这些Advisor的时候才会非常绕。 (根据用户配置 spring内置)
5、最后还要考虑到在什么时机实例化这个内置的Advisor呢?这里我们要保证Spring容器中第一个Bean实例化前的时候 要把Advisor实例化完整,因为无法保证第一个bean是否是需要代理。这里Spring内置了一个AspectJAwareAdvisorAutoProxyCreator。 这个类 继承了InstantiationAwareBeanPostProcessor、又实现了BeanPostProcessor其实两个方法主要功能如下:
①postProcessBeforeInstantiation() 初始化Advisor通知器
②postProcessAfterInitialization() 根据pointcutExpresion判断Bean是有适配的通知器、如果有那么就要开始生成代理。
所以还要注册AspectJAwareAdvisorAutoProxyCreator到容器中。
源码跟踪:
1、注册AspectJAwareAdvisorAutoProxy、Advisor、AspectJExpressionPointcut Bean定义信息进入容器
ConfigBeanDefinitionParser.parse()方法。
2、实例化Advisor
AbstractAutoProxyCreator.postProcessBeforeInstantiation()方法、这里要着重看下shouldSkip方法、"套娃"就发生在这里。
3、根据Pointcut 判断Bean是否需要代理 如果需要开始创建代理对象
AbstractAutoProxyCreator.wrapIfNecessary()
4、真正的创建代理(前面会判断jdk还是cglib)
CglibAopProxy.getProxy()