# 《Spring注解驱动开发》第42章:AnnotationAwareAspectJAutoProxyCreator深度解析
大家好,我是CurleyG~~
在《Spring注解驱动开发》系列中的《Spring中这么重要的AnnotationAwareAspectJAutoProxyCreator类是干嘛的? (opens new window)》一文中,我们简单分析了AnnotationAwareAspectJAutoProxyCreator类的作用,接下来,我们就以debug的方式来深入分析AnnotationAwareAspectJAutoProxyCreator的执行流程。
同样的,我们还是以debug的形式来分析AnnotationAwareAspectJAutoProxyCreator类的执行流程,在io.mykit.spring.plugins.register.config包下创建AopConfig类,然后在AopConfig类中创建mathHandler()方法,如下所示。
package io.mykit.spring.plugins.register.config;
import io.mykit.spring.plugins.register.aop.MathHandler;
import io.mykit.spring.plugins.register.aspect.LogAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* @author binghe
* @version 1.0.0
* @description 测试AOP
*/
@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
@Bean
public MathHandler mathHandler(){
return new MathHandler();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
接下来,在AopConfig#mathHandler()方法中打上断点,如下所示。

接下来,启动io.mykit.spring.test包下的AopTest#testAop01()方法。
package io.mykit.spring.test;
import io.mykit.spring.plugins.register.aop.MathHandler;
import io.mykit.spring.plugins.register.config.AopConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author binghe
* @version 1.0.0
* @description 测试切面
*/
public class AopTest {
@Test
public void testAop01(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AopConfig.class);
MathHandler mathHandler = context.getBean(MathHandler.class);
mathHandler.add(1, 2);
context.close();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
发现断点会进入org.springframework.context.annotation包下的AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()方法,如下所示。

而此时的断点是定位到AnnotationConfigApplicationContext#AnnotationConfigApplicationContext()方法中调用refresh()方法的代码行。refresh()方法会刷新Spring容器。接下来,我们可以通过IDEA左下角的方法调用堆栈进入refresh()方法内部,如下所示。

此时发现refresh()方法位于org.springframework.context.support包下的AbstractApplicationContext类中。此时,会发现代码调用流程会定位在AbstractApplicationContext#refresh()方法中调用的registerBeanPostProcessors()方法代码行。如下所示。

registerBeanPostProcessors()方法的作用就是注册bean的后置处理器来拦截bean的创建。
接下来,进入registerBeanPostProcessors()方法,发现registerBeanPostProcessors()方法位于org.springframework.context.support包下的AbstractApplicationContext类中,如下所示。

接下来,进入PostProcessorRegistrationDelegate#registerBeanPostProcessors()方法,这个方法的作用就是注册bean的后置处理器。在这个方法中按照顺序依次做了如下操作:
(1)先获取容器中已经定义的需要创建对象的所有BeanPostProcessor
(2)为容器中添加别的BeanPostProcessor
(3)注册实现了PriorityOrdered接口的BeanPostProcessor
(4)注册实现了Ordered接口的BeanPostProcessor
(5)注册没有实现优先级接口的BeanPostProcessor
(6)注册BeanPostProcessor,也就是创建BeanPostProcessor对象保存到容器中,创建interalAutoProxyCreator的BeanPostProcessor对象(AnnotationAwareAspectJAutoProxyCreator类型的对象)。
在(6)中又会依次执行如下几个步骤。
调用
createBeanInstance(String, RootBeanDefinition, Object[])方法,创建Bean的实例调用
populateBean(String, RootBeanDefinition, BeanWrapper)方法,为bean的属性赋值。调用
initializeBean(String, Object ,RootBeanDefinition mbd)方法,初始化bean。
这三个方法都位于org.springframework.beans.factory.support包下的AbstractAutowireCapableBeanFactory类中。
而第3)步的执行又会依次执行如下几个步骤。
- 调用
invokeAwareMethods(String, Object)方法,处理Aware接口的方法回调。 - 调用
applyBeanPostProcessorsBeforeInitialization(Object, String)方法,应用后置处理器的PostProcessorsBeforeInitialization()方法。 - 调用
invokeInitMethods(String, Object, RootBeanDefinition)方法,执行自定义的初始化方法。 - 调用
applyBeanPostProcessorsAfterInitialization(Object, String)方法,执行后置处理器的postProcessAfterInitialization(Object, String)方法。如下所示。
BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)创建成功,名称为aspectJAdvisorsBuilder。

接下来,我们看看方法的调用信息。

会发现此时逻辑调用会定位在BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); 这行代码上。
同样的,我们进入beanFactory.getBean(ppName, BeanPostProcessor.class);方法。发现会进入org.springframework.beans.factory.support包下的AbstractBeanFactory#getBean(String,Class)方法。

继续进入doGetBean()方法,会发现逻辑执行定位到doGetBean()中如下代码处。
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
2
3
4
5
6
7
8
9
10
11
12

而在IOC容器中第一次调用getSingleton()方法时,不会存在实例,所以,第一次调用getSingleton()方法会返回null。
进入getSingleton()方法,如下所示。

此时,发现Spring会调用singletonFactory.getObject()方法,继续往下执行,会发现逻辑定位到doGetBean()方法的如下代码。

继续执行断点,会发现逻辑进入org.springframework.beans.factory.support包下的AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])方法中,如下所示。

继续进入doCreateBean(String,RootBeanDefinition,Object[])方法,如下所示。

此时,会发现bean已经实例化完成了,如下所示。

接下来,就会初始化bean的信息。那具体bean是在哪里进行实例化的呢?我们找到doCreateBean(String,RootBeanDefinition,Object[])方法的如下代码片段。

同时,我们也会发现此时实例化的bean的类型为org.springframework.aop.config.internalAutoProxyCreator。

实例化完成之后就会在doCreateBean(String,RootBeanDefinition,Object[])方法的如下代码处进行初始化。

进入initializeBean(String, Object ,RootBeanDefinition mbd)方法。

会发现代码执行逻辑定位在invokeAwareMethods(beanName, bean);处。进入invokeAwareMethods(beanName, bean);方法。

这个方法就比较简单了,相信点击都能看懂,这里就不再赘述这个方法的逻辑了。此时,代码的执行逻辑会定位到((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);。
继续执行会发现逻辑进入了org.springframework.aop.framework.autoproxy包下的AbstractAdvisorAutoProxyCreator#setBeanFactory()方法,如下所示。

首先,会调用父类的setBeanFactory(BeanFactory)方法,然后会调用initBeanFactory(ConfigurableListableBeanFactory)方法初始化BeanFactory。
继续往下执行,我们会发现调用的是org.springframework.aop.aspectj.annotation包下的AnnotationAwareAspectJAutoProxyCreator#initBeanFactory(ConfigurableListableBeanFactory)方法。

继续往下执行,代码逻辑会执行到org.springframework.beans.factory.support包下的AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])方法中,并且会定位到Object beanInstance = doCreateBean(beanName, mbdToUse, args);代码行。

执行完会回到org.springframework.beans.factory.support包下的DefaultSingletonBeanRegistry#getSingleton(String, ObjectFactory<?>)方法,并且会执行`addSingleton(beanName, singletonObject);代码行,如下所示。

将bean放入容器中。
至此,整个bean的创建,实例化,初始化,添加到容器的过程就介绍完了。
