Spring AOP源码—<aop:config/>AOP配置标签解析一万字
Posted 刘Java
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring AOP源码—<aop:config/>AOP配置标签解析一万字相关的知识,希望对你有一定的参考价值。
基于最新Spring 5.x,对Spring AOP中的<aop:config/>标签的解析源码进行了详细分析,这是Spring AOP源码的入口!
此前我们已经详细学习了Spring AOP的基本使用,现在我们来学习Spring AOP的源码,学习AOP源码的前提要求是会使用AOP,同时要求我们了解IoC容器初始化的相关源码,否则很多的方法和和名词会让人摸不着头脑,比如bean定义是什么?如何注册bean定义?等等,这些都是IoC源码的核心知识点,我们此前的文章花费了大量时间和文字去讲解Spring IoC容器初始化的源码,在此不做赘述,默认大家都是了解的!
Spring AOP源码 系列文章
Spring AOP源码(1)—<aop:config/>AOP配置标签解析
Spring AOP源码(2)—AspectJAwareAdvisorAutoProxyCreator创建代理对象
Spring AOP源码(3)—invoke代理方法的调用与执行增强
Spring AOP源码(4)—基于注解的AOP源码解析以及AnnotationAwareAspectJAutoProxyCreator
Spring AOP源码(5)—DefaultAdvisorAutoProxyCreator自动代理创建者
文章目录
- Spring AOP源码 系列文章
- 1 Spring AOP源码概述
- 2 < aop:config/> AOP配置标签解析
- 2.1 configureAutoProxyCreator配置自动代理创建者
- 2.2. parsePointcut解析< aop:pointcut/>切入点标签
- 2.3 parseAdvisor解析通知器标签
- 2.4 parseAspect解析< aop:aspect/>切面标签
- 3 < aop:config/> 案例
- 4 < aop:config/> 标签解析总结
1 Spring AOP源码概述
在此前IoC容器初始化(3)的文章中,我们说过,对于扩展标签的解析是在parseCustomElement方法中完成的,不同扩展标签的解析,是根据该标签的本地名称去从NamespaceHandlerSupport的parsers缓存中获取对应的BeanDefinitionParser解析器来完成的。
对于aop命名空间下的系列的标签的解析器,都是通过AopNamespaceHandler注册到parsers缓存中的,从该类中我们能知道所有aop系列标签及其子标签的解析器:
/**
* aop 命名空间处理器
*/
public class AopNamespaceHandler extends NamespaceHandlerSupport
/**
* 注册一些列的BeanDefinitionParser,用于解析<aop:config/>
* <aop:aspectj-autoproxy/>、<aop:scoped-proxy/>、<aop:spring-configured/>标签及其子标签
*/
@Override
public void init()
// 在2.0以及2.5之后的xsd文件中均有的标签
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
//2.5及其之后的xsd文件中,该标签被移除,因此Spring 5.x版本的XML配置中不能使用该标签了
//实际上是被移动到context命名空间中了
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
< aop:scoped-proxy/>是作用域代理标签,用于装饰bean,改变其生命周期,将暴露出来的bean的生命周期控制在正确的范围类,用的比较少。 < aop:config/>用于基于XML配置AOP,< aop:aspectj-autoproxy/>用于基于XML开启AOP注解自动配置的支持,也就是支持@Aspect切面类及其内部的AOP注解,另外还有@EnableAspectJAutoProxy注解也能够开启AOP注解自动配置的支持,用于彻底摆脱XML文件。
从现在开始,接下来的几篇文章中,我们主要学习 < aop:config/>标签、< aop:aspectj-autoproxy/>标签、@EnableAspectJAutoProxy等注解的解析源码,以及代理对象的创建源码,以及代理对象的调用源码。实际上,当学完了AOP的源码之后我们就会知道基于注解和基于XML的AOP配置最终都是殊途同归的,就像基于XML和注解的IoC容器初始化的源码一样,注解和XML的配置终究都要融于一个容器中。
2 < aop:config/> AOP配置标签解析
我们先学习基于XML的AOP配置,也就是< aop:config/>标签的解析源码,后面我们会继续学习基于注解的AOP配置解析的相关源码。
我们从ConfigBeanDefinitionParser.parser方法的源码开始阅读!该方法的目的就是解析< aop:config/>标签及其子标签,当这些标签封装为对应类型的bean定义。
private static final String POINTCUT = "pointcut";
private static final String ADVISOR = "advisor";
private static final String ASPECT = "aspect";
/**
* ConfigBeanDefinitionParser的方法
* 解析<aop:config/>标签及其子标签
*
* @param element <aop:config/>标签元素
* @param parserContext 解析上下文
* @return 解析结果,固定返回null
*/
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext)
//新建一个CompositeComponentDefinition类型的bean定义,名称就是标签名 aop:config
//内部保存了多个ComponentDefinition,基于XML的source默认为null
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
//存入解析上下文内部的containingComponents集合中,入栈顶
parserContext.pushContainingComponent(compositeDef);
/*
* 尝试向容器注入或者升级AspectJAwareAdvisorAutoProxyCreator类型的自动代理创建者bean定义,专门用于后续创建AOP代理对象
* 这个类还实现了比如BeanClassLoaderAware、BeanFactoryAware、SmartInstantiationAwareBeanPostProcessor、
* InstantiationAwareBeanPostProcessor、BeanPostProcessor …… 等一系列的自动回调接口,它们在创建代理对象的过程中非常有用
*
* <aop:config/>标签使用AspectJAwareAdvisorAutoProxyCreator创建代理,实际上还有很多创建者可以用于创建代理对象
* 比如<aop:aspectj-autoproxy/>以及@EnableAspectJAutoProxy使用AnnotationAwareAspectJAutoProxyCreator
* <tx:annotation-driven/>以及@EnableTransactionManagement使用InfrastructureAdvisorAutoProxyCreator
* 不同的标签或者注解使用不同的创建者,但容器最终只会创建一个bean定义,采用优先级最高的自动代理创建者的类型,我们后面会讲到
*/
configureAutoProxyCreator(parserContext, element);
//获取<aop:config/>标签下的所有子标签结点元素
List<Element> childElts = DomUtils.getChildElements(element);
//遍历解析
for (Element elt : childElts)
//获取子标签本地名称,即去除"aop:"之后的名称
String localName = parserContext.getDelegate().getLocalName(elt);
//如果是 <aop:pointcut/> 标签
if (POINTCUT.equals(localName))
/*
* 调用parsePointcut方法解析 <aop:pointcut/> 标签
*/
parsePointcut(elt, parserContext);
//如果是 <aop:advisor/> 标签
else if (ADVISOR.equals(localName))
/*
* 调用parseAdvisor方法解析 <aop:advisor/> 标签
*/
parseAdvisor(elt, parserContext);
//如果是 <aop:aspect/> 标签
else if (ASPECT.equals(localName))
/*
* 调用parseAspect方法解析 <aop:aspect/> 标签
*/
parseAspect(elt, parserContext);
//出栈并注册,并不是注册到注册表中……,可能什么也不做
parserContext.popAndRegisterContainingComponent();
//返回null
return null;
//--------栈操作---------
/**
* ParserContext的属性,存放一系列的组件bean定义
* 这是一个ArrayDeque集合,可以模拟栈
*/
private final Deque<CompositeComponentDefinition> containingComponents = new ArrayDeque<>();
/**
* ParserContext的方法
* 存入containingComponents栈顶
*/
public void pushContainingComponent(CompositeComponentDefinition containingComponent)
this.containingComponents.push(containingComponent);
/**
* ParserContext的方法
* 栈顶元素出栈并注册
*/
public void popAndRegisterContainingComponent()
//注册组件
registerComponent(popContainingComponent());
/**
* ParserContext的方法
* 栈顶元素出栈
*/
public CompositeComponentDefinition popContainingComponent()
return this.containingComponents.pop();
/**
* 注册组件,并不是注册到注册表中……
*/
public void registerComponent(ComponentDefinition component)
//获取但不移除最新栈顶元素
CompositeComponentDefinition containingComponent = getContainingComponent();
//如果栈顶元素不为null,那么当前组件加入到栈顶元素的内部集合中
if (containingComponent != null)
containingComponent.addNestedComponent(component);
//否则,通过readerContext发布组件注册事件,默认也是个空方法,啥都没干……
else
this.readerContext.fireComponentRegistered(component);
/**
* 获取但不移除最新栈顶元素
*/
@Nullable
public CompositeComponentDefinition getContainingComponent()
return this.containingComponents.peek();
2.1 configureAutoProxyCreator配置自动代理创建者
configureAutoProxyCreator方法用于尝试向容器注入或者升级一个AspectJAwareAdvisorAutoProxyCreator类型的自动代理创建者bean定义,beanName为"org.springframework.aop.config.internalAutoProxyCreator",专门用于后续创建AOP代理对象。
这个类还实现了比如BeanClassLoaderAware、BeanFactoryAware、SmartInstantiationAwareBeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor …… 等一系列的自动回调接口,它们在创建代理对象的过程中非常有用。这些也是Spring的强扩展性的根本。
< aop:config/>标签使用AspectJAwareAdvisorAutoProxyCreator创建代理,实际上还有很多创建者可以用于创建代理对象,比如< aop:aspectj-autoproxy/>以及@EnableAspectJAutoProxy使用AnnotationAwareAspectJAutoProxyCreator,< tx:annotation-driven/>以及@EnableTransactionManagement使用InfrastructureAdvisorAutoProxyCreator,不同的标签或者注解使用不同的创建者,但容器最终只会创建一个bean定义,采用优先级最高的自动代理创建者的类型,我们后面会讲到。
/**
1. ConfigBeanDefinitionParser的方法
2. <p>
3. 通过<aop:config/>标签的解析触发调用,尝试配置AspectJAwareAdvisorAutoProxyCreator类型的自动代理创建者的bean定义到容器
*/
private void configureAutoProxyCreator(ParserContext parserContext, Element element)
//调用AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary方法
AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);
可以看到,该方法直接委托AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary方法继续操作!
2.1.1 registerAspectJAutoProxyCreatorIfNecessary注册自动代理创建者
分为三步:
- 调用AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary,尝试注册或者升级一个名为"org.springframework.aop.config.internalAutoProxyCreator",类型为AspectJAwareAdvisorAutoProxyCreator的自动代理创建者的bean定义。
- 调用useClassProxyingIfNecessary,解析proxy-target-class与expose-proxy属性。
- 调用registerComponentIfNecessary注册组件,这里的注册是指存放到外层方法新建的CompositeComponentDefinition对象的内部集合中或者广播事件,而不是注册到注册表中。
这几个方法都是通用方法,我们在后面的文章中还会见到,到时候不再赘述!
/**
* AopNamespaceUtils的方法
* <p>
* 如有必要,注册AspectJAwareAdvisorAutoProxyCreator
*/
public static void registerAspectJAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement)
/*
* 1 尝试注册或者升级一个名为"org.springframework.aop.config.internalAutoProxyCreator"
* 类型为AspectJAwareAdvisorAutoProxyCreator的自动代理创建者的bean定义
*/
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
/*
* 2 解析proxy-target-class与expose-proxy属性
* proxy-target-class用于设置代理模式,默认是优先JDK动态代理,其次CGLIB代理,可以指定为CGLIB代理
* expose-proxy用于暴露代理对象,主要用来解决同一个目标类的方法互相调用时代理不生效的问题
*/
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
/*
* 3 注册组件,这里的注册是指存放到外层方法新建的CompositeComponentDefinition对象的内部集合中或者广播事件,而不是注册到注册表中
*/
registerComponentIfNecessary(beanDefinition, parserContext);
2.1.1.1 registerAspectJAutoProxyCreatorIfNecessary注册/升级自动代理创建者
AopConfigUtils的同名方法,内部继续调用registerOrEscalateApcAsRequired方法,由于解析的< aop:config />标签,因此第一个参数是AspectJAwareAdvisorAutoProxyCreator.class类型。
/**
1. AopConfigUtils的方法
2. <p>
3. 如有必要,注册自动代理创建者,类型为AspectJAwareAdvisorAutoProxyCreator.class
*/
@Nullable
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source)
/*
* 继续调用registerOrEscalateApcAsRequired方法
* 由于解析的<aop:config />标签,因此第一个参数是AspectJAwareAdvisorAutoProxyCreator.class
*/
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
2.1.1.1.1 registerOrEscalateApcAsRequired注册/升级自动代理创建者
核心方法终于到了,从源码中就可以看出“升级”或者“新增”的逻辑:
容器最终只会创建一个自动代理创建者bean定义,采用优先级最高的自动代理创建者的类型。
首先尝试获取名为"org.springframework.aop.config.internalAutoProxyCreator
"的bean定义,如果已存在,那么比较bean定义中的自动代理创建者的类型和当前参数传递的自动代理创建者的类型的优先级,如果当前参数传递的自动代理创建者的类型的优先级更高,那么那么bean定义的beanClass属性设置为使用当前参数传递的自动代理创建者的类型的className,即升级bean定义,最后返回null。
设置bean定义的order属性优先级最高,也就是说将会最先被应用并尝试创建代理对象。
- 如果没有该名字的bean定义,那么使用当前参数class类型,也就是AspectJAwareAdvisorAutoProxyCreator.class类型作为beanClass,
新建
一个RootBeanDefinition类型的bean定义,以"org.springframework.aop.config.internalAutoProxyCreator
"为beanName,通过registerBeanDefinition注册到容器中(该方法在此前IoC容器初始化(3)的源码文章中已经讲过了)。最后返回新增的bean定义。
/**
* AopConfigUtils的属性
* <p>
* Spring内部管理的自动代理创建者的 beanName
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
/**
1. AopConfigUtils的方法
2. <p>
3. 注册或者修改自动代理创建者的bean定义
4. 5. @param cls 自动代理创建者的class,用于比较优先级或者创建bean定义
6. @param registry 注册表
7. @param source 源数据
*/
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source)
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
/*
* 如果包含名为"org.springframework.aop.config.internalAutoProxyCreator"的bean定义
* 那么可能会升级bean定义的beanClass属性,Spring容器只会保存一个优先级最高的自动代理创建者的bean定义
*/
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME))
//获取bean定义
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//如果当前bean定义的类型不是参数的类型,那么选择优先级最高的类型
if (!cls.getName().equals(apcDefinition.getBeanClassName()))
//获取当前bean定义中的自动代理创建者的类型优先级,实际上就是存储在APC_PRIORITY_LIST集合的索引位置
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
//获取当前参数传递的自动代理创建者的类型优先级,实际上就是存储在APC_PRIORITY_LIST集合的索引位置
int requiredPriority = findPriorityForClass(cls);
//如果bean定义中的自动代理创建者的类型优先级 小于 当前参数传递的自动代理创建者的类型优先级
if (currentPriority < requiredPriority)
//那么bean定义的beanClass属性设置为使用 当前参数传递的自动代理创建者的类型的className,即升级bean定义
apcDefinition.setBeanClassName(cls.getName());
//直接返回null,表示没有创建新的bean定义
return null;
//到这里,表示需要创建新的bean定义
//新建一个RootBeanDefinition类型的bean定义,beanClass使用当前参数class类型
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
//设置order属性优先级最高,也就是说将会最先被应用并尝试创建代理对象
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
/*
* 调用registerBeanDefinition方法注册这个新的BeanDefinition到注册表的缓存中,
* 名为"org.springframework.aop.config.internalAutoProxyCreator"
*
* 该方法在此前"IoC容器初始化(3)"的源码文章中已经讲过了,这是核心方法
*/
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
//返回新增的bean定义
return beanDefinition;
2.1.1.1.1.1 findPriorityForClass获取class的优先级
该方法用于获取自动类型创建者的优先级。实际上就是从AopConfigUtils的APC_PRIORITY_LIST集合汇总查找该class的索引位置并返回,找不到就抛出异常“Class name xxx is not a known auto-proxy creator class”。
APC_PRIORITY_LIST集合在AopConfigUtils类加载的时候就在静态块中按顺序初始化了一系列的自动代理创建者的类型,索引位置就是优先级,因此优先级大小为:InfrastructureAdvisorAutoProxyCreator.class < AspectJAwareAdvisorAutoProxyCreator.class < AnnotationAwareAspectJAutoProxyCreator.class。
实际上,在上一个方法中:
- 如果是解析< tx:annotation-driven />标签或者@EnableTransactionManagement事物注解,那么cls参数是InfrastructureAdvisorAutoProxyCreator.class;
- 如果是解析< aop:config />标签,那么cls参数是AspectJAwareAdvisorAutoProxyCreator.class;
- 如果是解析< aop:aspectj-autoproxy />标签或者@EnableAspectJAutoProxy注解,那么cls参数是AnnotationAwareAspectJAutoProxyCreator.class。
所以说,如果我们设置了< aop:config />和< aop:aspectj-autoproxy />两个标签,那么最终会注册AnnotationAwareAspectJAutoProxyCreator类型的自动代理创建者。
//---------AopConfigUtils的相关属性--------
/**
* 按升序顺序存储的自动代理创建者的类型集合
* 可以看到,默认有三种类型,优先级就是比较索引顺序的大小,因此优先级为:
* InfrastructureAdvisorAutoProxyCreator < AspectJAwareAdvisorAutoProxyCreator < AnnotationAwareAspectJAutoProxyCreator
* <p>
* 如果是解析<tx:annotation-driven />标签或者@EnableTransactionManagement事物注解,那么cls参数是InfrastructureAdvisorAutoProxyCreator.class
* 如果是解析<aop:config />标签,那么cls参数是AspectJAwareAdvisorAutoProxyCreator.class
* 如果是解析<aop:aspectj-autoproxy />标签或者@EnableAspectJAutoProxy注解,那么cls参数是AnnotationAwareAspectJAutoProxyCreator.class
*/
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);
static
// Set up the escalation list...
//按先后顺序添加三种类型
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
/**
1. AopConfigUtils的方法
2. <p>
3. 返回当前类型的自动代理创建者的优先级,实际上就是存储的索引位置
*/
private static int findPriorityForClass(@Nullable String className)
for (int i = 0; i < APC_PRIORITY_LIST.size(); i++)
Class<?> clazz = APC_PRIORITY_LIST.get(i);
if (clazz.getName().equals(className))
//返回索引
return i;
//没找到就抛出异常
throw new IllegalArgumentException(
"Class name [" + className + "] is not a known auto-proxy creator class");
2.1.1.2 useClassProxyingIfNecessary解析proxy-target-class、expose-proxy属性
在升级或者注册了自动代理创建者的bean定义之后,这一步用于解析、设置proxy-target-class和expose-proxy属性到这个bean定义的proxyTargetClass和exposeProxy属性中。
- proxy-target-class属性用于设置代理模式,默认为false,即优先JDK动态代理,其次CGLIB代理,可以设置为true,表示强制为CGLIB代理。
- expose-proxy属性用于暴露代理对象,主要用来解决同一个目标类的方法互相调用时代理不生效的问题。默认值为false表示不开启,设置为true表示开启,可以在代码中通过AopContext.currentProxy()获取当前代理类对象。
//------AopNamespaceUtils的相关属性--------
/**
* aop相关标签的proxy-target-class属性名常量,用于设置代理的模式
*/
public static final String PROXY_TARGET_CLASS_ATTRIBUTE = "proxy-target-class";
/**
* aop相关标签的expose-proxy属性名常量,用于设置是否暴露代理对象
*/
private static final String EXPOSE_PROXY_ATTRIBUTE = "expose-proxy";
/**
* AopNamespaceUtils的方法
* <p>
* 解析设置proxy-target-class和expose-proxy属性
*
* @param registry 注册表
* @param sourceElement 标签元素
*/
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement)
if (sourceElement != null)
//获取proxy-target-class属性值,默认false,即优先采用JDK动态代理,不满足则采用CGLIB代理
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
//如果设置为true,那么强制走CGLIB代理
if (proxyTargetClass)
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
//获取expose-proxy属性值,默认false,即不暴露代理对象
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
//如果设置为true,那么暴露代理对象
if (exposeProxy)
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
2.1.1.2.1 forceAutoProxyCreatorToUseClassProxying强制使用CGLIB代理
如果proxy-target-class属性为true,那么强制使用CGLIB创建代理对象,这里仅仅是设置bean定义的proxyTargetClass属性值为true,后面才会用到。这实际上是顶级父类ProxyConfig的属性。
/**
* AopConfigUtils的属性
* <p>
* Spring内部管理的自动代理创建者的 beanName
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
/**
* AopConfigUtils的方法
* <p>
* 强迫AutoProxyCreator使用基于类的代理,也就是CGLIB代理
*/
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry)
//如果包含名为"org.springframework.aop.config.internalAutoProxyCreator"的bean定义
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME))
//那么获取该bean定义
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
//添加属性proxyTargetClass设置值为true,表示强制使用CGLIB代理
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
2.1.1.2.2 forceAutoProxyCreatorToExposeProxy强制暴露代理对象
如果expose-proxy属性为true,那么强制暴露代理对象,这里仅仅是设置bean定义的exposeProxy属性值为true,后面才会用到。这实际上是顶级父类ProxyConfig的属性。
/**
* AopConfigUtils的属性
* <p>
* Spring内部管理的自动代理创建者的 beanName
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
/**
* AopConfigUtils的方法
* <p>
* 强迫AutoProxyCreator暴露代理对象
*/
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) 曹工说Spring Boot源码(16)-- Spring从xml文件里到底得到了什么(aop:config完整解析上)