【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?

在这里插入图片描述

作者简介:zhz小白
公众号:小白的Java进阶之路
专业技能:
1、Java基础,并精通多线程的开发,熟悉JVM原理
2、熟悉Java基础,并精通多线程的开发,熟悉JVM原理,具备⼀定的线上调优经验
3、熟悉MySQL数据库调优,索引原理等,⽇志原理等,并且有出过⼀篇专栏
4、了解计算机⽹络,对TCP协议,滑动窗⼝原理等有⼀定了解
5、熟悉Spring,Spring MVC,Mybatis,阅读过部分Spring源码
6、熟悉SpringCloud Alibaba体系,阅读过Nacos,Sentinel,Seata,Dubbo,Feign,Gateway核⼼源码与设计,⼆次开发能⼒
7、熟悉消息队列(Kafka,RocketMQ)的原理与设计
8、熟悉分库分表ShardingSphere,具有真实⽣产的数据迁移经验
9、熟悉分布式缓存中间件Redis,对其的核⼼数据结构,部署架构,⾼并发问题解决⽅案有⼀定的积累
10、熟悉常⽤设计模式,并运⽤于实践⼯作中
11、了解ElasticSearch,对其核⼼的原理有⼀定的了解
12、了解K8s,Jekins,GitLab
13、了解VUE,GO
14、⽬前有正在利⽤闲暇时间做互游游戏,开发、运维、运营、推销等

本人著作git项目:https://gitee.com/zhouzhz/star-jersey-platform,有兴趣的可以私聊博主一起编写,或者给颗star
领域:对支付(FMS,FUND,PAY),订单(OMS),出行行业等有相关的开发领域
如果此文还不错的话,还请关注、点赞、收藏三连支持一下博主~

文章目录

  • 1、@EnableAspectJAutoProxy有什么用?
  • 2、@EnableAspectJAutoProxy的源码解析
    • 2.1、初入@EnableAspectJAutoProxy源码
    • 2.2、@Import注解引入AspectJAutoProxyRegistrar
    • 2.3、开始阅读AspectJAutoProxyRegistrar源码
    • 2.4、开始阅读AnnotationAwareAspectJAutoProxyCreator
      • 2.4.1、AnnotationAwareAspectJAutoProxyCreator的类结构图
      • 2.4.2、开始阅读AnnotationAwareAspectJAutoProxyCreator的源码,了解其内部运作
        • 2.4.2.1、debug一下AnnotationConfigApplicationContext
        • 2.4.2.2、org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class...)
        • 2.4.2.3、org.springframework.context.support.AbstractApplicationContext#refresh
        • 2.4.2.4、org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
        • 2.4.2.5、org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)
        • 2.4.2.6、org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
        • 2.4.2.7、org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory)
        • 2.4.2.8、org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
        • 2.4.2.9、org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
        • 2.4.2.10、org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
        • 2.4.2.11、org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
        • 2.4.2.12、org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory
        • 2.4.2.13、AnnotationAwareAspectJAutoProxyCreator是怎么执行的?
      • 2.4.3、汇总以下AnnotationAwareAspectJAutoProxyCreator的处理
      • 2.4.4、AnnotationAwareAspectJAutoProxyCreator的作用是什么呢?
        • 2.4.4.1、postProcessBeforeInstantiation
        • 2.4.4.2、postProcessAfterInitialization
  • 原文连接(本人其他平台)

1、@EnableAspectJAutoProxy有什么用?

  • @EnableAspectJAutoProxy代表我们可以开启注解版的AOP功能,也就是说我们要想使用注解版的AOP,就必须在启动类/配置类(@Configuration)中添加@EnableAspectJAutoProxy。

2、@EnableAspectJAutoProxy的源码解析

废话不多说,让我们来看一下@EnableAspectJAutoProxy的核心源码吧

2.1、初入@EnableAspectJAutoProxy源码

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第1张图片

2.2、@Import注解引入AspectJAutoProxyRegistrar

首先看AspectJAutoProxyRegistrar之前我们可以先行去了解下@Import注解如何注册一个Bean,具体如下:【Spring【IOC】】——7、@Import注解给容器中快速导入一个组件
接着我们再来进入AspectJAutoProxyRegistrar中,可以发现它继承了ImportBeanDefinitionRegistrar,重写了其中的void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);方法,源码如下:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第2张图片

所以我们可以知道**@EnableAspectJAutoProxy注解使用AspectJAutoProxyRegistrar对象自定义组件,并将相应的组件添加到了IOC容器中。**
那么大家好不好奇为什么他要通过AspectJAutoProxyRegistrar去继承ImportBeanDefinitionRegistrar,然后在其实现方法中注册一个Bean呢?那么这个Bean是什么呢?接下来我们开始debug其源码,从而深入去探讨@EnableAspectJAutoProxy。

2.3、开始阅读AspectJAutoProxyRegistrar源码

我们先在AspectJAutoProxyRegistrar的registerBeanDefinitions方法中添加一个断点,如下
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第3张图片

然后我们一直进去,先后会执行以下代码

  • org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry)
    • org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
      • org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired

一直到org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired中我们就可以看到其核心逻辑,代码如下:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第4张图片

我们可以发现他在第一次进来的时候其实会创建一个key为:org.springframework.aop.config.internalAutoProxyCreator
,value: AnnotationAwareAspectJAutoProxyCreator.class的RootBeanDefinition并返回。
然后我们执行完这个方法之后,就会回来到下面红圈里面的方法,这一行的本质是将注解中的所有属性转成Map。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第5张图片

具体的结果如下所示:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第6张图片

  • 通过AnnotationConfigUtils类的attributesFor()方法来获取@EnableAspectJAutoProxy注解的信息。
    • 判断proxyTargetClass属性的值是否为true
      • 若为true则调用AopConfigUtils类的forceAutoProxyCreatorToUseClassProxying()方法;
        • 【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第7张图片

        • 这里就是获取AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,然后往属性中设置"proxyTargetClass"=true

    • 判断exposeProxy属性的值是否为true
      • 若为true则调用AopConfigUtils类的forceAutoProxyCreatorToExposeProxy()方法,本质是暴露一些Bean
        • 【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第8张图片

        • 这里就是获取AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,然后往属性中设置"exposeProxy"=true。

至此AspectJAutoProxyRegistrar类就已经完结了。
综上所述,向Spring的配置类上添加@EnableAspectJAutoProxy注解之后,会向IOC容器中注册AnnotationAwareAspectJAutoProxyCreator,也就是创建注解装配模式的AspectJ切面自动代理创建器

2.4、开始阅读AnnotationAwareAspectJAutoProxyCreator

上面2.3中我们发现@EnableAspectJAutoProxy注解本质上是往容器中添加一个AnnotationAwareAspectJAutoProxyCreator类,那么我们是不是要去了解AnnotationAwareAspectJAutoProxyCreator是一个什么样的东西呢?

2.4.1、AnnotationAwareAspectJAutoProxyCreator的类结构图

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第9张图片

2.4.2、开始阅读AnnotationAwareAspectJAutoProxyCreator的源码,了解其内部运作

首先我们可以通过debug程序,具体可以先去看一下前面的章节《20、搭建一个AOP测试环境?》,我们主要是根据这个程序去研究AnnotationAwareAspectJAutoProxyCreator后置处理器的实现。
我们可以先去看一下栈帧,如下
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第10张图片

2.4.2.1、debug一下AnnotationConfigApplicationContext

首先我们debug之后,会发现他会先停在AnnotationConfigApplicationContext这个创建对象上,如下
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第11张图片

2.4.2.2、org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(java.lang.Class…)

然后接着来会进入到AnnotationConfigApplicationContext内部调用refresh()方法区刷新容器,刷新容器就是要把容器中的所有bean都创建出来,也就是说这就像初始化容器一样。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第12张图片

2.4.2.3、org.springframework.context.support.AbstractApplicationContext#refresh

我们会进入refresh()方法里面的,并且会执行到下面这一行重要代码,

//注册Bean处理器,然后拦截bean创建。
registerBeanPostProcessors(beanFactory);

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第13张图片

2.4.2.4、org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors

然后我们进入registerBeanPostProcessors方法中,看一下其核心实现,她就是调用了 PostProcessorRegistrationDelegate的registerBeanPostProcessors(beanFactory, this)静态方法。代码如下:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第14张图片

2.4.2.5、org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)

首先我们先全局看一下这个方法的代码,代码如下:

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
		// WARNING: Although it may appear that the body of this method can be easily
		// refactored to avoid the use of multiple loops and multiple lists, the use
		// of multiple lists and multiple passes over the names of processors is
		// intentional. We must ensure that we honor the contracts for PriorityOrdered
		// and Ordered processors. Specifically, we must NOT cause processors to be
		// instantiated (via getBean() invocations) or registered in the ApplicationContext
		// in the wrong order.
		//
		// Before submitting a pull request (PR) to change this method, please review the
		// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
		// to ensure that your proposal does not result in a breaking change:
		// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
		//先按照类型拿到IOC容器中所有需要创建的后置处理器,即先获取IOC容器中已经定义了的需要创建对象的所有BeanPostProcessor
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		/**
		 * 在已有的BeanPostProcessor中,如下
		 * 0 = {ApplicationContextAwareProcessor@2260}
		 * 1 = {ApplicationListenerDetector@2261}
		 * 2 = {ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@2262}
		 * 添加一个下面的BeanPostProcessor检查器,
		 * 3 = {PostProcessorRegistrationDelegate$BeanPostProcessorChecker@2264}
		 */
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			} else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

接着我们开始讲解一下这段代码的意思,让我们充分了解每一行的来源,然后我们进入到PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);方法中,此时会按照下面流程执行

  • 1、先按照类型拿到IOC容器中所有需要创建的后置处理器,即先获取IOC容器中已经定义了的需要创建对象的所有BeanPostProcessor。(Spring在创建IOC容器的时候会先传入配置类,然后配置类中会有一个注解@EnableAspectJAutoProxy,而这个注解会注册一个AnnotationAwareAspectJAutoProxyCreator后置处理器(看前面),还有一些spring默认的后置处理器和我们自定义的后置处理器,具体如下)。

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第15张图片

接着我们继续看下去,发现他执行了,下面这行代码去添加一个beanPostProcessor,
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));具体意思如下:
在这里插入图片描述

然后我们我们可以继续看到其下面有四行代码,如下:

//实现了PriorityOrdered接口
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
//类型是MergedBeanDefinitionPostProcessor的BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
//实现了Ordered接口
List<String> orderedPostProcessorNames = new ArrayList<>();
//原生的BeanPostProcessor
List<String> nonOrderedPostProcessorNames = new ArrayList<>();

其作用是什么呢?主要是分离BeanPostProcessor,不同的BeanPostProcessor的执行顺序不同,具体为上面的代码解释。

  • 优先注册实现了PriorityOrdered接口的BeanPostProcessor
    • 如果类型是MergedBeanDefinitionPostProcessor的BeanPostProcessor
  • 再给容器中注册实现了Ordered接口的BeanPostProcessor
  • 最后再注册没实现优先级接口的BeanPostProcessor

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第16张图片

我们可以自行查看一下org.springframework.aop.config.internalAutoProxyCreator的Bean名称的组件,即是AnnotationAwareAspectJAutoProxyCreator,他的底层类ProxyProcessorSupport实现了Ordered,所以他最终会进入到orderedPostProcessorNames这个list中,代码如下:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第17张图片

接着他会按照以下顺序是去执行注册BeanPostProcessor,如下:

  • 注册是priority的BeanPostProcessor
  • 注册是ordered的BeanPostProcessor
  • 注册原生的BeanPostProcessor
  • 注册是priority并且类型是MergedBeanDefinitionPostProcessor的BeanPostProcessor
  • 注册一个ApplicationListenerDetector的检测器(注册一个新的)

然后这个方法我们就讲完了。

2.4.2.6、org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

然后他会按照下面的执行顺序去执行代码:

  • org.springframework.beans.factory.BeanFactory#getBean(java.lang.String, java.lang.Class)
    • org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class)
      • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

就会执行到我们这个部分要讲的核心代码了,这段代码有点长,我们直接看核心,在这段代码中有个函数表达式,关于函数表达式的执行顺序,大家可以看一下下面的数字,他会按照0-4执行。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第18张图片
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第19张图片

省略代码来看就是下面:

AbstractBeanFactory#200 
// 0
sharedInstance = this.getSingleton(beanName, () -> { 
    try {
        return this.createBean(beanName, mbd, args);// 3 
    } catch (BeansException var5) {
        this.destroySingleton(beanName); 
            throw var5;
    } 
});

DefaultSingletonBeanRegistry#113
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {// 1 
    singletonObject = singletonFactory.getObject();// 2
        ...// 4 
}

我们分析一下这段代码,他其实就是从容器中获取单例Bean,具体的逻辑也就是下一部分的核心代码逻辑。

2.4.2.7、org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory)

第一次创建Bean的时候,是会执行到下面的DefaultSingletonBeanRegistry类的getSingleton()方法中,如果是第一次获取单实例的Bean获取不到时,就会调用singletonObject = singletonFactory.getObject();也就是下面截图的代码那
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第20张图片

2.4.2.8、org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

接着debug他就会到AbstractBeanFactory的doGetBean()方法中,我们可以见名思意发现他就是创建Bean的,也就是说如果getSingleton获取不到Bean的话,我们就通过createBean创建Bean。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第21张图片

2.4.2.9、org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

接着我们会经历很长的一部分调用,知道调到AbstractAutowireCapableBeanFactory#createBean方法,执行流程如下:

  • org.springframework.beans.factory.support.AbstractBeanFactory#createBean
    • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

源代码如下,他会一直执行到doCreateBean方法
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第22张图片

2.4.2.10、org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

然后当他执行到doCreateBean()方法,准备创建Bean的时候,这个方法会做很多事情,比如Bean的实例化,Bean的属性填充,Bean的初始化,销毁等等,但是对于我们这个AnnotationAwareAspectJAutoProxyCreator的后置处理器来说,他是在执行到exposedObject = initializeBean(beanName, exposedObject, mbd);方法,就会处理的,因此我们直接看initializeBean()初始化方法。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第23张图片

接下来他会进入到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)方法中。

2.4.2.11、org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

在进入到initizeBean之后,他会进行一系列的aware回调,其中有一段逻辑他是他会当我们的Bean实现了BeanFactoryAware,他就会把BeanFactory设置成AbstractAutowireCapableBeanFactory,而恰巧我们的AnnotationAwareAspectJAutoProxyCreator他就实现了BeanFactoryAware,具体大家可以看上面的解释,然后他就又会去调用所有的BeanPostProcessor的postProcessBeforeInitialization()方法,再调用初始化方法,也就是init-method,InitializingBean的相关方法,最后执行BeanPostProcessor的postProcessAfterInitialization()方法。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第24张图片
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第25张图片

我们上面讲到了他会执行BeanFactoryAware相关的实现类,那么我们是不是可以定位到org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory方法

2.4.2.12、org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#setBeanFactory

他会进入到AbstractAdvisorAutoProxyCreator的setBeanFactory中去设置BeanFactory,然后会执行到initBeanFactory()中,去初始化BeanFactory。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第26张图片

然后就会调到AnnotationAwareAspectJAutoProxyCreator#initBeanFactory中执行以下代码,主要是创建两个类ReflectiveAspectJAdvisorFactory和BeanFactoryAspectJAdvisorsBuilderAdapter,相当于把之前创建的aspectJAdvisorFactory以及beanFactory重新包装了一下。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第27张图片

因此整个流程就讲完了。

2.4.2.13、AnnotationAwareAspectJAutoProxyCreator是怎么执行的?

AnnotationAwareAspectJAutoProxyCreator它实现了SmartInstantiationAwareBeanPostProcessor并且继承了InstantiationAwareBeanPostProcessor,所以他的初始化前后的方法名分别为postProcessBeforeInstantiation,postProcessAfterInstantiation,而在我们上面讲的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])方法中,在其里面调用了如下代码:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第28张图片

在resolveBeforeInstantiation()方法里面调用了applyBeanPostProcessorsBeforeInstantiation()和applyBeanPostProcessorsAfterInitialization()两个方法。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第29张图片

其内部的逻辑分别是,从而调用了继承InstantiationAwareBeanPostProcessor的类的两个实例化前后方法

@Nullable
	protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
			Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
			if (result != null) {
				return result;
			}
		}
		return null;
	}

@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

所以我们可以得出结论:

  • AnnotationAwareAspectJAutoProxyCreator会在任何bean创建之前,先尝试返回bean的实例
  • AnnotationAwareAspectJAutoProxyCreator在所有bean创建之前,会有一个拦截,因为它是InstantiationAwareBeanPostProcessor这种类型的后置处理器,然后会调用它的postProcessBeforeInstantiation()方法。

2.4.3、汇总以下AnnotationAwareAspectJAutoProxyCreator的处理

  • org.springframework.context.support.AbstractApplicationContext#refresh
  • org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors
  • org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)
  • org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class)
  • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
  • org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory)
  • org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
  • 最后就是执行initializeBean的里面的
    • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization
    • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
  • 至此AnnotationAwareAspectJAutoProxyCreator就创建完成了,最后拿到所有的BeanPostProcessor,然后调用beanFactory的addBeanPostProcessor()方法将BeanPostProcessor注册到BeanFactory中。(这里可以看一下PostProcessorRegistrationDelegate#registerBeanPostProcessors(ConfigurableListableBeanFactory,AbstractApplicationContext)里面的),我们可以看一下registerBeanPostProcessors(beanFactory, internalPostProcessors);因为AnnotationAwareAspectJAutoProxyCreator会放入internalPostProcessors中,就可以发现他的本质就是上面红色那句话。
    【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第30张图片
    【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第31张图片

2.4.4、AnnotationAwareAspectJAutoProxyCreator的作用是什么呢?

首先我们通过上面的内容可知,在每一个bean创建之前,都会调用**postProcessBeforeInstantiation()**方法,**postProcessAfterInitialization()**方法。所以我们重点看一下AnnotationAwareAspectJAutoProxyCreator的
**postProcessBeforeInstantiation()postProcessAfterInitialization()**方法。

2.4.4.1、postProcessBeforeInstantiation

我们直接看AbstractAutoProxyCreator的postProcessBeforeInstantiation方法,他是AnnotationAwareAspectJAutoProxyCreator的核心,具体代码如下:
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第32张图片

解析:

  • 1、先获取缓存的key,可以发现如果BeanName为空,就返回BeanClass,BeanName不为空,就判断当前beanClass是否是FactoryBean,是的话就返回&+beanName,不是的话就返回beanName。
    【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第33张图片

  • 2、判断名为targetSourcedBeans的Set集合里面是否包含有这个bean的名称,但是targetSourcedBeans是一个空的集合

    • 2.1、判断当前bean是否在advisedBeans中
      • advisedBeans:里面保存了所有需要增强的bean的名称
      • 为什么叫需要增强的bean?简单理解就是通过aop切面代理后的bean,列如日志aop类大家应该都熟悉吧。
        【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第34张图片
  • 3、判断当前bean是否是基础类型,或者是否是切面(标注了@Aspect注解的)

    • 3.1、我们可以发现isInfrastructureClass方法中,他执行了两块代码,分别是
      • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#isInfrastructureClass
        【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第35张图片
      • org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#isInfrastructureClass
        【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第36张图片
      • 可以总结出isInfrastructureClass:判断当前bean是否是基础类型,或者是否是切面(标注了@Aspect注解的),其中基础类型涉及的注解有Advice,Pointcut,Advisor,AopInfrastructureBean。
    • 3.2、判断是否需要跳过
      • 在这里首先是调用findCandidateAdvisors()方法找到候选的增强器的集合:所谓的增强器其实就是切面里面的那些通知方法,只不过,在这儿是把通知方法的详细信息包装成了一个Advisor,并将其存放在了一个List集合中,即增强器的集合,即是说,每一个通知方法都会被认为是一个增强器。并且每一个通知方法都是InstantiationModelAwarePointcutAdvisor类型的,并且我们还可以发现是@Aspect修饰的类的aop方法。
        【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第37张图片
        【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第38张图片

      • 判断当前Advisor是否是AspectJPointcutAdvisor这种类型的,如果是,那么返回true。然而在我们这肯定不是,因为都是InstantiationModelAwarePointcutAdvisor类型的,所以不会进,因此会调用super.shouldSkip(beanClass, beanName)

        • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip
          在这里插入图片描述
          • org.springframework.aop.framework.autoproxy.AutoProxyUtils#isOriginalInstance,这里会判断当前的beanName是否为空或者beanName的长度不等于beanClass的长度+“.ORIGINAL"的长度,是的话就返回false,不是的话就判断beanName的开始是否等于beanClass的名字和beanName的结束是否等于”.ORIGINAL"。
            【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第39张图片
  • 4、如果是配置类,比如我们前面的章节里面的MainConfig的话,那么3就会返回false,就不会执行if里面的语句。并且下面中TargetSource也会为空,所以postProcessBeforeInstantiation()方法整体会返回null。

因此,我们可以发现,在每次创建bean的时候,都会先调用postProcessBeforeInstantiation()方法,然后再调用postProcessAfterInitialization()方法。

2.4.4.2、postProcessAfterInitialization

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第40张图片

解析(我们还是基于MainConfig来讲):

  • 1、首先我们看一下传入当前方法的Bean是否为空,我们很清晰的可以发现bean就是ManConfig,所以他要进入if。

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第41张图片

  • 2、先获取缓存的key,可以发现如果BeanName为空,就返回BeanClass,BeanName不为空,就判断当前beanClass是否是FactoryBean,是的话就返回&+beanName,不是的话就返回beanName。所以对于我们当前来说,他返回的就是mainConfig。

在这里插入图片描述

  • 3、判断名为earlyProxyReferences的Set集合里面是否包含当前bean,在该Set集合里面我们可以看到之前已经代理过了什么,目前该Set集合是一个空集合。因为当前earlyProxyReferences是肯定不包括,所以会进入到wrapIfNecessary(bean, beanName, cacheKey)。
    【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第42张图片

  • 4、判断哪些情况下是需要包装的。(wrapIfNecessary()方法调用完之后,最终会给容器中返回当前组件使用cglib增强了的代理对象

    • 4.1、首先是拿到MainConfig这个bean的名称(即mainConfig),然后再来判断名为targetSourcedBeans的Set集合里面是否包含有这个bean的名称,只不过此时该Set集合是一个空集合。

    • 4.2、判断名为advisedBeans的Map集合里面是否包含有当前bean的名称。我在前面也说过了advisedBeans这个东东,它就是一个Map集合,里面保存了所有需要增强的bean的名称。

    • 4.3、由于这儿是第一次来处理当前bean,所以名为advisedBeans的Map集合里面是不包含MainConfig这个bean的名称的。

    • 4.4、判断当前bean是否是基础类型,或者是否是切面(标注了@Aspect注解的)
      【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第43张图片

      • 4.4.1、我们可以发现isInfrastructureClass方法中,他执行了两块代码,分别是

        • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#isInfrastructureClass
          【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第44张图片

        • org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#isInfrastructureClass
          【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第45张图片

        • 可以总结出isInfrastructureClass:判断当前bean是否是基础类型,或者是否是切面(标注了@Aspect注解的),其中基础类型涉及的注解有Advice,Pointcut,Advisor,AopInfrastructureBean。

      • 4.4.2、判断是否需要跳过

        • 在这里首先是调用findCandidateAdvisors()方法找到候选的增强器的集合:所谓的增强器其实就是切面里面的那些通知方法,只不过,在这儿是把通知方法的详细信息包装成了一个Advisor,并将其存放在了一个List集合中,即增强器的集合,即是说,每一个通知方法都会被认为是一个增强器。并且每一个通知方法都是InstantiationModelAwarePointcutAdvisor类型的,并且我们还可以发现是@Aspect修饰的类的aop方法。
          【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第46张图片
          【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第47张图片

        • 判断当前Advisor是否是AspectJPointcutAdvisor这种类型的,如果是,那么返回true。然而在我们这肯定不是,因为都是InstantiationModelAwarePointcutAdvisor类型的,所以不会进,因此会调用super.shouldSkip(beanClass, beanName)

          • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#shouldSkip
            在这里插入图片描述

            • org.springframework.aop.framework.autoproxy.AutoProxyUtils#isOriginalInstance,这里会判断当前的beanName是否为空或者beanName的长度不等于beanClass的长度+“.ORIGINAL"的长度,是的话就返回false,不是的话就判断beanName的开始是否等于beanClass的名字和beanName的结束是否等于”.ORIGINAL"。
              在这里插入图片描述
      • 4.4.3、如果上面两条件有一个是true的话,就设置增强advisedBeans的map为cacheKey,false。然后返回bean。

    • 4.5、获取当前bean的所有增强器,调用getAdvicesAndAdvisorsForBean()方法获取当前bean的所有增强器,也就是那些通知方法,最终封装成这样一个Object[] specificInterceptors数组。
      在这里插入图片描述

      • 4.5.1、org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean
        • 4.5.1.1、org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
          • 4.5.1.1.1、获取所有的mainConfig的这个类型的所有的可用的增强器
            【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第48张图片

            • 4.5.1.1.1.1、进入其中就可以发现,其第一步是获取候选的所有增强器,也就是@Aspect的各种定义的通知类型方法(前置,后置,环绕,后置。。。)
              【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第49张图片
              【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第50张图片
            • 4.5.1.1.1.2、找到候选的所有增强器,也就是说是来找哪些通知方法是需要切入到当前bean的目标方法中的。
              在这里插入图片描述
              • 4.5.1.1.1.2.1、org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply,它是用AopUtils工具类来找到所有能用的增强器(通知方法)的。
                【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第51张图片
                • 4.5.1.1.1.2.1.1、然后我们可以进入到org.springframework.aop.support.AopUtils#findAdvisorsThatCanApply,看一下其核心源码,本质上就是表达式匹配所有可用的增强器,从而把他添加到一个list中,并返回
                  【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第52张图片

最后一个canApply的源码。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第53张图片

           - 4.5.1.1.1.3、如果eligibleAdvisors不为空,就会进行排序,也就是说调用哪些通知方法,是有顺序的。然后进行返回。

【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第54张图片
- 4.5.1.2、如果findEligibleAdvisors(beanClass, beanName)返回为空,就返回null,也就是空Object[],返回就正常返回。
【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第55张图片
- 4.5.2、现在specificInterceptors的Object[]数组里面已经具有了那些指定好的增强器,这些增强器其实就是要拦截目标方法执行的。
- 4.5.3、总结一下
- 找到候选的所有增强器,也就是说是来找哪些通知方法是需要切入到当前bean的目标方法中的
- 获取到能在当前bean中使用的增强器
- 给增强器排序

  • 4.6、保存当前bean在advisedBeans中,表示这个当前bean已经被增强处理了
    【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第56张图片

    • 接着进入到createProxy中,也就是最核心的创建代理的方法,具体代码流程如下:
      • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
        • org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildProxy,这里我们只看最后一步,其他代码都是一些过滤。
          【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第57张图片

          • proxyFactory.getProxyClass(classLoader),一般情况下不会调用当前方法,因此我们可以看一下前面传进来的classOnly他是false,重点看下面这个。
          • proxyFactory.getProxy(classLoader)),具体代码如下,我们直接看一下getProxy的实现。
            【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第58张图片
            【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第59张图片
            【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第60张图片
            • 我们可以发现getProxy会有两个实现,一个是jdk,一个是cglib,spring会分析如果当前类是有实现接口的,那么就使用jdk来创建动态代理,如果当前类没有实现接口,此时jdk是没法创建动态代理的,那么自然就得使用cglib来创建动态代理了。对于我们当前来说是cglib,spring也可以设置所有的代理都用cglib,只需要配置类开启@EnableAspectJAutoPrxy(proxyTargetClass = true),具体的更详细的可以自行百度。
              【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第61张图片
  • 4.7、设置代理类,返回
    【Spring【AOP】】——21、@EnableAspectJAutoProxy注解详解?_第62张图片
    总结:

  • 获取所有增强器,所谓的增强器就是切面里面的那些通知方法。

  • 然后再把这些增强器保存到代理工厂(即proxyFactory)中。

  • 为当前组件创建代理对象,并且会有两种形式的代理对象,它们分别如下,最终Spring会自动决定,是为当前组件创建jdk的动态代理,还是创建cglib的动态代理。

    • 一种是JdkDynamicAopProxy这种形式的,即jdk的动态代理
    • 一种是ObjenesisCglibAopProxy这种形式的,即cglib的动态代理

原文连接(本人其他平台)

https://www.yuque.com/zhzbaishen/ldbu6i/epbql4eoegtomgce?singleDoc# 《21、@EnableAspectJAutoProxy注解详解?》

你可能感兴趣的:(#,Spring,spring,java,后端)