上节我们在Spring注解驱动开发AOP功能的篇幅中简单的通过案例来回顾了AOP的注解驱动开发的基本过程,同时也提过到一点,并不是我们的重点,本节我们来分析AOP底层源码是如何运作的,首先我们从注解@EnableAspectJAutoProxy作为我们的分析的入口。
当我们点进去之后发现:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
这是Spring注解驱动编程的套路,在Springboot中我们会大量的看到同样的编码分割,其中上述源码中最重要的是注解@Import({AspectJAutoProxyRegistrar.class})的作用,简单的在这里说下该注解的作用:
- @Import:一般是用来帮助我们导入其他的组件,在后面的篇幅我们再来介绍它的使用这里大家只需要知道是帮助我们导入其他组件就可以了,在此处是帮助我们导入组件AspectJAutoProxyRegistrar.class
既然是导入组件AspectJAutoProxyRegistrar.class,接下来我们来看看这个组件,继续点击进去来到:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
AspectJAutoProxyRegistrar() {
}
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
发现我们的组件AspectJAutoProxyRegistrar竟然实现了ImportBeanDefinitionRegistrar接口,简单的说一下该接口的作用:
ImportBeanDefinitionRegistrar 的作用
在整个spring容器技术中,我们都知道创建一个对象只需要在对应的bean上添加注解@Bean,这种方式是按照Spring的规定来帮助我们进行对象的创建,如下面这段代码:
@Bean
public MathCalculator calculator(){
return new MathCalculator();
}
其中,Spring创建MathCalculator 的以方法名为name属性规则创建的,当然我们也可以指定要创建bean的name,只需通过注解@Bean的value属性指定,代码如下:
@Bean(value = "calculator1")
public MathCalculator calculator(){
return new MathCalculator();
}
上述只是创建bean的一种方式,实际上Spring还为我们提供了一种自定义的创建bean的方式,也就是只要我们实现接口ImportBeanDefinitionRegistrar 即可,我们可以按照自己规则来完成bean的创建,我们来看相关源码
- 该接口位于org.springframework.context.annotation包下:
public interface ImportBeanDefinitionRegistrar {
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
this.registerBeanDefinitions(importingClassMetadata, registry);
}
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
}
在该接口我们发现有空实现的方法,此方法就需要我们来完成实现逻辑,由于篇幅有限本篇不在啰嗦了,大家只需知道有这样一种方式即可,后续我会进行相关知识和入门案例的编写,
了解了ImportBeanDefinitionRegistrar的作用之后,我们发下组件AspectJAutoProxyRegistrar实现其中的方法,通过Dbug我们来跟踪下代码的流程走向,其中在方法的实现中我们发现这段代码:
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
从字面意思来看来理解这段代码的意思就是如果需要注册一个切面注解代理生成器,有点蒙,不过没关系,我们Dbug来跟一下代码来到
AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry)这个方法
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, (Object)null);
}
此方法又调用内部的两个参数的方法,接着Dbug进去我们来到:
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
同样该方法调用了内部方法registerOrEscalateApcAsRequired(...),其大致作用是:如果是一个必要的组件,向容器中注册或者来升级一下它,其组件的类型是AnnotationAwareAspectJAutoProxyCreator.clss,其实到这一步就知道了,原来是要给我们的容器中注册一个AnnotationAwareAspectJAutoProxyCreator ,不方,到这一步可以继续Dbug代码,也可以不用了,我们作为学者不妨在来看看该方法的实现,代码如下:
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
} else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", -2147483648);
beanDefinition.setRole(2);
registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
return beanDefinition;
}
}
Aop源码分析1.png代码总体不是很难理解,Dbug截图如下:
上图也就是我们方法的参数,其中registry 为Bean定义信息的注册器,cls就是AnnotationAwareAspectJAutoProxyCreator此类型,简单的来理解下这段代码的逻辑
-
首先判断我们的registry注册器中是否包含org.springframework.aop.config.internalAutoProxyCreator 类型,很显然代码是不会进if条件的,因为我们是第一次注册,肯定不在的,这里也说明了一点我们要注册的AnnotationAwareAspectJAutoProxyCreator bean的真实类型为 internalAutoProxyCreator ,接着来到else分支,我们接着看:
-
无非就是注册internalAutoProxyCreator 的bean的定义信息
到这一步我们自定义要创建的bean 【internalAutoProxyCreator 】也就完成了 ,我们也发现目前所有的核心都聚焦在AnnotationAwareAspectJAutoProxyCreator 这个类上,接下来的重点来分析它
AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator.png该类位于 org.springframework.aop.aspectj.annotation包下,其继承实现关系如下图所示:
SmartInstantiationAwareBeanPostProcessor.png上述就是AnnotationAwareAspectJAutoProxyCreator 的继实现关系图,其中需要我们留意的是接口SmartInstantiationAwareBeanPostProcessor,此接口是一个后置处理器,我们来看下该接口的类图信息:
其主要的作用是在Bean的初始化完成前后进行一些额外的操作,这是所有BeanPostProcessor【后置处理器】的作用
- 不难发现在我们的 AbstractAutoProxyCreator中存在这样一段代码:
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
- 在我们的AbstractAdvisorAutoProxyCreator类中同样是有这样一段代码:
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
} else {
this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);
}
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
this.advisorRetrievalHelper = new AbstractAdvisorAutoProxyCreator.BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
}
这里首先调用的是AbstractAutoProxyCreator #setBeanFactory(...)方法进行赋值
-
同样在AbstractAutoProxyCreator中有方法#postProcessBeforeInstantiation(...)beanFactory初始化前的处理方法
-
同样在AbstractAutoProxyCreator中有方法#postProcessAfterInstantiation(...)beanFactory初始化后的处理逻辑
-
同样在我们的子类AnnotationAwareAspectJAutoProxyCreator中存在初始化beanFactory的#initBeanFactory(...)方法,实际调用AbstractAdvisorAutoProxyCreator#initBeanFactory(...)完成bean的初始化
上述简单叙述了BeanPostProcessor的出现的时机和具体的处理逻辑,在接下来我们来走一遭Spring给我们创建AnnotationAwareAspectJAutoProxyCreator 这个bean的流程
AnnotationAwareAspectJAutoProxyCreator的创建流程
首先来到我们的启动类如下:
//Aop测试
@Test
public void testAop(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAop.class);
MathCalculator calculator = applicationContext.getBean(MathCalculator.class);
calculator.div(10,5);
applicationContext.close();
}
全程Dbug走一遭,在我们的AnnotationConfigApplicationContext这一行打上断点,首先会来到类AnnotationConfigApplicationContext中下面方法:
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}
其参数为我们的配置类,该方法其主要是帮助我们创建IOC容器和以及注册我们的配置类信息到容器中,最后通过方法refresh()完成对容器的初始化
- 继续Dbug this.refresh()方法我们来到类AbstractApplicationContext的#refresh()方法,其中有这样一段代码需要我们注意一下:
this.registerBeanPostProcessors(beanFactory);
其主要的作用是通过BeanPostProcessor【后置处理器】的拦截操作方便我们对bean的创建,继续Dbug代码来到当前类AbstractApplicationContext的方法:
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
image.png
图中是方法参数的具体类型,从代码的实现我们看到的是调用PostProcessorRegistrationDelegate#registerBeanPostProcessors(...)两个参数方法,继续Dbug来到方法:
- 一进方法我们发现:
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
Aop源码分析2.png上述代码片段主要是通过bean的名称类型来获取当前容器的后置处理器,具体的类型有:
- 接着我们也看到它通过如下代码片段:
beanFactory.addBeanPostProcessor(new PostProcessorRegistrationDelegate.BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
继续来到方法#addBeanPostProcessor 中,其主要的是添加一些别的后置处理器,代码片段如下:
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
this.beanPostProcessors.remove(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
this.beanPostProcessors.add(beanPostProcessor);
}
代码简单这里就不啰嗦了,还是回到我们的上面的核心方法里,期间定义了一些空的集合如:
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList();
List<BeanPostProcessor> internalPostProcessors = new ArrayList();
List<String> orderedPostProcessorNames = new ArrayList();
List<String> nonOrderedPostProcessorNames = new ArrayList();
接着是for循环 分类处理我们获取到后置处理器,从代码的片段来看:
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
这其中优先注册实现了PriorityOrdered这个接口的BeanPostProcessor其次是:
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
} else {
nonOrderedPostProcessorNames.add(ppName);
}
接着是处理实现了Ordered接口的后置处理器和普通的后置处理器【BeanPostProcessor】,通过for循环的分类处理之后,我们看到如下片段代码:
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
对这些BeanPostProcessor的后置处理器进行排序,因为每个后置处理器的执行先后是有顺序的,接着看:
registerBeanPostProcessors(beanFactory, (List)priorityOrderedPostProcessors);
private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
Iterator var2 = postProcessors.iterator();
while(var2.hasNext()) {
BeanPostProcessor postProcessor = (BeanPostProcessor)var2.next();
beanFactory.addBeanPostProcessor(postProcessor);
}
}
上述代码主要是处理beanFactory类型的后置处理器,具体大家参看接口BeanFactoryPostProcessor,该接口是是Spring中的一个拓展接口,其主要的目的是在beanFactory类型的bean标准初始化之后我们可以定制修改BeanFactory的内容
- 该接口位于org.springframework.beans.factory.config包下,代码片段如下:
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory var1) throws BeansException;
}
接口中有一个方法需要我们实现可以自定义BeanFactory的内容,还是回到我们的位置上来,接着往下看到如下的代码片段:
List<BeanPostProcessor> orderedPostProcessors = new ArrayList(orderedPostProcessorNames.size());
Iterator var14 = orderedPostProcessorNames.iterator();
while(var14.hasNext()) {
String ppName = (String)var14.next();
BeanPostProcessor pp = (BeanPostProcessor)beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
image.png上述代码getBean(...)实质上是创建我们对象internalAutoProxyCreator的过程,Dbug截图如下,看了更了然:
ppName告诉我们是从容器中获取internalAutoProxyCreator bean实例,继续Dbug进去来到类AbstractBeanFactory#getBean(String name, Class<T> requiredType)此方法,代码片段如下:
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return this.doGetBean(name, requiredType, (Object[])null, false);
}
image.png
图中红框里的是参数的具体类型,接着我们看#doGetBean(...)方法,虽然代码很长,但大致意思我们还是可以理解的,这里不在一一去介绍,我们只说关键性的代码片段,这也是阅读源码的一个技巧,没必要要把每一行的代码都理解,只需要大概的明白是干啥的就行,扯远了接着看如下的代码片段:
String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
doGetBean方法一进来首先通过#transformedBeanName(...)对我们的bean进行简单的处理,其实就是获取要创建的bean的name,可能有的bean的名字是别名,接着通过name去获取bean实例,很显然第一次是获取不到的,接着进行一系列的判断处理,至于里面的逻辑这里就不提了,不是我们关系的,感兴趣的可以自己Dbug走一圈代码就明白了,下面的代码片段才是我们创建bean的入口:
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
image.png
AbstractAutowireCapableBeanFactory.png也就是我们的createBean(...)方法,我们继续跟踪代码来到类AbstractAutowireCapableBeanFactory中,该类位于org.springframework.beans.factory.support包下,其继承实现关系如下图:
这不是重点,我们接着看创建bean的过程,首先我们来看如下的代码片段:
beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse)
image.png
图中所示的是方法参数,其中参数mbdToUse中描述的是当前要创建bean的属性,如是否单例等进去方法我们来到:
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = this.determineTargetType(beanName, mbd);
if (targetType != null) {
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = bean != null;
}
return bean;
}
代码其主要的作用是获取bean实例,当然由于我们才要创建bean,因此此处返回的bean是null的,返回createBean方法,由于通过上述方式我们获取到的bean是null,接着代码会来到如下片段:
beanInstance = this.doCreateBean(beanName, mbdToUse, args);
上述方法才是我们创建Bean的最后一道工序,继续跟踪代码来到:
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
image.png通过上述方法的处理,这里我们拿到了通过包装之后的类型AnnotationAwareAspectJAutoProxyCreator,其真实类型为org.springframework.aop.config.internalAutoProxyCreator
从上述Dbug的过程来看,是对我们internalAutoProxyCreator这个bean进行了包装,继续跟踪代码:
Object bean = instanceWrapper.getWrappedInstance();
image.png
这个代码片段获取包装的bean实例AnnotationAwareAspectJAutoProxyCreator的一些属性,接着跟踪代码:
this.populateBean(beanName, mbd, instanceWrapper);
上述代码片段主要是给我们要创建的bean进行属性的装备过程至于方法具体的逻辑这里不在细看,感兴趣的自己可以去看看,当我们bean的属性装配完成之后进行我们bean的实例化过程,代码片段如下:
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
继续跟踪代码来到方法#initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) ,在方法中首先通过如下代码片段:
this.invokeAwareMethods(beanName, bean);
通过方法来处理实现了Aware接口的bean,具体实现如下:
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware)bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = this.getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware)bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware)bean).setBeanFactory(this);
}
}
}
代码简单就不在啰嗦了,接着来到如下的代码的片段:
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
此方法之前我们也提过,主要是在bean初始化之前来进行一些操作的,继续跟踪代码来到:
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
上述这段代码处理的逻辑是这样的,获取当前所有的BeanPostProcessor,然后调用#postProcessBeforeInitialization(...)进行相关逻辑的处理
图中看到的 是当前拿到的后置处理器和容器中的bean,具体干了什么我们进去看看次方法:
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware) && !(bean instanceof EmbeddedValueResolverAware) && !(bean instanceof ResourceLoaderAware) && !(bean instanceof ApplicationEventPublisherAware) && !(bean instanceof MessageSourceAware) && !(bean instanceof ApplicationContextAware)) {
return bean;
} else {
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareInterfaces(bean);
return null;
}, acc);
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
}
image.png
上述在bean初始化之前操作完成时,接着来到:
this.invokeInitMethods(beanName, wrappedBean, mbd);
image.png通过此方法执行bean的初始化操作
最后通过如下方法:
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
在bean初始化完成之后通过调用#applyBeanPostProcessorsAfterInitialization(...)方法进行其他操作,继续跟踪代码来到:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Object current;
for(Iterator var4 = this.getBeanPostProcessors().iterator(); var4.hasNext(); result = current) {
BeanPostProcessor processor = (BeanPostProcessor)var4.next();
current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
}
return result;
}
我们可以发现的是还是先获取所有的后置处理器,然后遍历调用#postProcessAfterInitialization(....)方法去完成
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
最后发现后置处理器直接将创建的bean给我们返回到容器中,也就是我们的AnnotationAwareAspectJAutoProxyCreator这个bean完成了真正的创建,最后我们来到类:PostProcessorRegistrationDelegate中的#registerBeanPostProcessors(...)方法的代码片段:
registerBeanPostProcessors(beanFactory, (List)nonOrderedPostProcessors);
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, (List)internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
通过方法 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext))将我们的创建的AnnotationAwareAspectJAutoProxyCreator 添加到beanFactory中,继续跟踪代码来到:
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
this.beanPostProcessors.remove(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
this.beanPostProcessors.add(beanPostProcessor);
}
image.png
到这里我们的AnnotationAwareAspectJAutoProxyCreator 完成了注册和创建过程
网友评论