Spring 源码阅读 58:配置 ProxyFactory 的 Advisor 列表
概述
本文接着上一篇分析 Spring 创建 AOP 代理对象的createProxy
方法。之前分析了 ProxyFactory 的创建、基础的配置参数,以及如何通过后处理器的配置和 Bean 类型实现的接口信息,来配置 ProxyFactory 的proxyTargetClass
属性,这个属性决定了创建代理对象时是通过 JDK 动态代理的方式创建还是 CGLIB 方式创建。
构建 Advisor 列表
先回到createProxy
方法的代码中。
本文开始分析下面的这部分:
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
首先,会调用buildAdvisors
方法,构建一个 Advisor 列表,方法中的参数specificInterceptors
就是在调用createProxy
方法时传入的参数,也就是之前从 Spring 容器中找到的与当前 Bean 对象匹配的增强逻辑的集合。这里为什么还要构建一次 Advisor 的列表呢,我们进入方法查看。
buildAdvisors 方法
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#buildAdvisors
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
allInterceptors.addAll(Arrays.asList(specificInterceptors));
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
先整体看一下这个方法的流程。首先,通过resolveInterceptorNames
方法得到一个 Advisor 列表commonInterceptors
,名称翻译过来就是普通拦截器。然后,将commonInterceptors
和specificInterceptors
都添加到实现声明的allInterceptors
。最后,遍历allInterceptors
中的元素,通过调用成员变量advisorAdapterRegistry
的wrap
方法处理成 Advisor 对象后,得到方法最终的结果。
接下来详细分析,先进入resolveInterceptorNames
方法查看。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#resolveInterceptorNames
private Advisor[] resolveInterceptorNames() {
BeanFactory bf = this.beanFactory;
ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
List<Advisor> advisors = new ArrayList<>();
for (String beanName : this.interceptorNames) {
if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
Object next = bf.getBean(beanName);
advisors.add(this.advisorAdapterRegistry.wrap(next));
}
}
return advisors.toArray(new Advisor[0]);
}
这个方法中,会根据interceptorNames
成员变量中保存的每一个拦截器名称,找到容器中对应的 Bean 实例,经过advisorAdapterRegistry
的wrap
方法的处理,得到最终返回的 Advisor 列表。
再看一下interceptorNames
里有什么:
/** Default is no common interceptors. */
private String[] interceptorNames = new String[0];
可以看到,默认情况下这个数组是空的,并且advisorAdapterRegistry
的wrap
方法我们后面还会分析到,所以resolveInterceptorNames
方法就分析到这里。
回到buildAdvisors
方法中,接着往下看。
接下来,会将commonInterceptors
和specificInterceptors
合并为一个allInterceptors
列表,合并时会进行判断,如果成员变量applyCommonInterceptorsFirst
的值时true
,则将commonInterceptors
添加到allInterceptors
头部,否则添加到尾部。这个属性的默认值是true
。
方法的最后,会通过成员变量advisorAdapterRegistry
的wrap
方法来处理allInterceptors
里的每一个拦截器。
advisorAdapterRegistry.wrap 方法
我们进入wrap
方法。
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
if (advice instanceof MethodInterceptor) {
// So well-known it doesn't even need an adapter.
return new DefaultPointcutAdvisor(advice);
}
for (AdvisorAdapter adapter : this.adapters) {
// Check that it is supported.
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
这个方法的逻辑比较简单,作用是将参数传入的拦截器对象(也就是上一步allInterceptors
集合中的每一个元素)封装成 Advisor 对象。
如果当前操作的拦截器类型本身就是 Advisor 的实现类,那么,将其原样返回即可。如果它不是 Advisor 的实现类,那么在判断它是否是 Advice 的实现类,如果不是,则抛出异常,也就是说,它只能是 Advisor 或者 Advice 的实现类。
之后就是 Advice 的情况。先判断它是不是 MethodInterceptor 的实现类,MethodInterceptor 是 Advice 的子接口,如果是 MethodInterceptor 的实现类的话,则将其封装为 DefaultPointcutAdvisor 返回。
最后,对于是 Advice 实现类,但不是 MethodInterceptor 实现类的情况,在进行下面的逻辑处理。
遍历adapters
成员变量中的每一个元素adapter
,adapters
中的内容可以从以下代码中看到:
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
/**
* Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
*/
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
初始状态下,这里有三个 Advice 适配器。在遍历过程中对正在处理的 Advice 类型的拦截器,调用adapter
的supportsAdvice
方法,判断遍历到的适配器是不是与当前的拦截器适配,如果得到结果true
,则将拦截器封装为 DefaultPointcutAdvisor 返回。如果adapters
中没有能够预知适配的适配器,则表示无法将当前的拦截器包装成 Advisor,会在wrap
方法的最后抛出异常。
其实适配器的supportsAdvice
方法就是判断拦截器的类型。
介绍完wrap
方法,buildAdvisors
方法的全部流程也就介绍完了。在createProxy
方法中,buildAdvisors
的结果会被添加到proxyFactory
的advisors
结合中。
接下来,还将目标类型targetSource
赋值给了proxyFactory
的相应属性。
customizeProxyFactory 方法
设置完advisors
和targetSource
属性之后,执行了customizeProxyFactory
方法。但这个方法是一个空方法。
protected void customizeProxyFactory(ProxyFactory proxyFactory) {
}
可以看出来,这是一个扩展点,通过在子类中重写这个方法,可以在 ProxyFactory 工厂对象的重要属性都配置完之后,在对其进行自定义的处理。
后续的步骤
接下来再看下一个代码片段。
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
这里又给proxyFactory
配置了两个属性,其中if语句的判断条件中advisorsPreFiltered
需要留意。
// org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#advisorsPreFiltered
protected boolean advisorsPreFiltered() {
return false;
}
在 AbstractAutoProxyCreator 中,这个方法返回了false
。但是,我们这里用到的创建 AOP 代理的后处理器,并不是 AbstractAutoProxyCreator 类型,而是它的子类,所以需要找到子类中与具体实现类关系最近的类中的方法实现。可以找到 AbstractAdvisorAutoProxyCreator 找到重写的方法实现,返回的是true
。
// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#advisorsPreFiltered
@Override
protected boolean advisorsPreFiltered() {
return true;
}
在createProxy
方法的最后,返回了通过调用proxyFactory的getProxy方法创建的代理对象。
return proxyFactory.getProxy(getProxyClassLoader());
具体的创建代理对象的原理,放到下篇文章中分析。
总结
本文分析了 Spring 创建 AOP 代理对象之前,初始化 ProxyFactory 对象的最后一部分逻辑,主要包含 Advisor 列表的构建。至此,可以看出,ProxyFactory 创建代理对象之前,最重要的配置内容就是创建代理对象的方式(JDK 动态代理或 CGLIB)以及增强逻辑的集合,接下来就进入了最后创建代理对象的过程。
转载自:https://juejin.cn/post/7157742171389427748