上篇文章分析了SpringAop
核心概念及其含义,从本节开始将剖析SpringAop
的底层运行原理,由于篇幅较长会分为多个文章进行输出。本节将详细以Proxy
为入口使用SpringAop
原生使用方式(不集成Spring)案例对底层原理进行剖析。
SpringAop
代理入口
啥是代理入口?
使用过SpringAop
框架的小伙伴都知道其底层是使用代理来实现的,SpringAop
通过某个类可以生成代理对象,这个类就是代理入口。
SpringAop
提供的代理入口
通过翻阅官方文档可以知道SpringAop
提供了 : ProxyFactory、ProxyFactoryBean、AspectJProxyFactory
这几个入口工厂。根据这些入口可以构建出如下UML
图:
ProxyFactory
: 该入口可以再不依赖SpringIoc
的情况下使用,相当于原生方式使用了。ProxyFactoryBean
: 该入口适用于集成Spring
情况下使用,该工厂依赖BeanFactory
.AspectJProxyFactoty
: 该入口适用于集成Spring
并且使用@Aspect
注解方式时使用
本文将以ProxyFactory
这个代理入口搭配案例进行剖析,因为这个入口是比较简单(纯粹)的。其他两个接口本质上也是在ProxyFactory
这个入口的原理的基础上增加了一些feture
, 所以只要搞懂ProxyFactory
其他两个理解也非常简单。
SpringAop
底层核心关键类剖析
开始剖析原理之前先把一些关键的类搞清楚,这样可以事半功倍。如上面UML
所示,和ProxyFactory
继承关系有关的类ProxyCreatorSupport、AdvisedSupport、ProxyConfig、Advised
。上篇文章已经介绍过Advised
了,此处不再赘述。
ProxyConfig
顾名思义这是个和代理配置有关的类,如下图所示是该类的核心源码。可以看出像proxyTargetClass、exposeProxy、frozen
这些属性好像在前面的Advised
接口中也出现过, 通过翻阅源码实际上这些属性就是对Advisoed
中的部分方法的实现,ProxyConfig
除了做相关实现还额外提供了几个属性和对属性设置默认值。
使用过SpringAop
开发的小伙伴应该对proxyTargetClass、exposeProxy
属性非常熟悉,是不是在哪里见过?使用SpringBoot
开发时一般都会在主启动类上添加一个@EnableAspectJAutoProxy
注解以开启基于AOP
注解方式的代理,这个注解就包含这两个属性。当在注解中配置了这两个属性的值时,底层会将注解中属性的值映射到ProxyConfig
中的proxyTargetClass、exposeProxy
中,只不过映射这一过程是SpringAop
帮我们做的。
public class ProxyConfig implements Serializable {
//设置是否使用CGLIB进行代理,默认false
private boolean proxyTargetClass = false;
//设置是否对通过CGLIB创建的代理应用积极的优化,默认不开启。
//无论是否开启对JDK代理都没有影响,除非非常了解AOP底层是如何优化的否则不建议开启
private boolean optimize = false;
//设置代理对象是否不可以直接转为Advised接口类型,默认为false可以转为Advised
//opaque属性的作用和frozen类似,都是为了对代理对象的保护,禁止修改代理对象。
boolean opaque = false;
//设置是否暴露代理对象,这里暴露的意思指的是将代理对象放入ThreadLocal中
//以便可以通过AopContext.currentProxy()随时取到代理对象
boolean exposeProxy = false;
//设置代理配是否被冻结,默认false。
//如果被冻结则代理生成后不能再通过Advised接口中的addAdvice、addAdvisor()动态添加配置,会报错。
//默认false则不冻结配置,说明可以在运行期间动态添加advice或advisor。
private boolean frozen = false;
public void copyFrom(ProxyConfig other) {
Assert.notNull(other, "Other ProxyConfig object must not be null");
this.proxyTargetClass = other.proxyTargetClass;
this.optimize = other.optimize;
this.exposeProxy = other.exposeProxy;
this.frozen = other.frozen;
this.opaque = other.opaque;
}
//省略get/set方法............
}
Advised(AdvisedSupport)
从之前的UML
图中可以了解到AdvisedSupport
实际上是对Advised
接口的实现。通常情况下这个类应该实现Advided
接口的所有方法,这边SpringAop
将Advised
接口中和代理属性相关的几个方法实现放到了ProxyConfig
中。又因为AdvisedSupport
继承了ProxnConfig
,所以也相当于实现了所有实现,只不过把和代理属性相关的方法放到了ProxyConfig
,这样做的目的是内聚性更强。
分析AdvisedSupport
源码之前,先看下它里面涉及的关键类。
TargetSource
TargetSource
接口主要用来获取目标对象(被代理的对象),SpringAop
提供了多个实现类。由于这个类比较重要所有后面将另起篇章单独剖析,此处先mark一下它是用来获取目标对象的即可。
MethodCacheKey
public class AdvisedSupport extends ProxyConfig implements Advised {
.......
private static final class MethodCacheKey implements Comparable<MethodCacheKey> {
private final Method method;
private final int hashCode;
public MethodCacheKey(Method method) {
this.method = method;
this.hashCode = method.hashCode();
}
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (other instanceof MethodCacheKey &&
this.method == ((MethodCacheKey) other).method));
}
......
@Override
public int compareTo(MethodCacheKey other) {
int result = this.method.getName().compareTo(other.method.getName());
if (result == 0) {
result = this.method.toString().compareTo(other.method.toString());
}
return result;
}
}
}
如上图所示MethodCacheKey
是AdvisedSupport
中的一个静态内部类,用于对Method
封装,使其具备比较功能。AdvisedSupport
中使用这个类主要用来缓存一个方法与该方法相关的advisor
之前的映射关系。
AdvisedSupport
public class AdvisedSupport extends ProxyConfig implements Advised {
//提供一个默认的目标对象,默认对象为null
public static final TargetSource EMPTY_TARGET_SOURCE = EmptyTargetSource.INSTANCE;
TargetSource targetSource = EMPTY_TARGET_SOURCE;
//标识当前AdvisedSupport中的Advisor是否已经对特定的目标类进行了过滤,默认false
private boolean preFiltered = false;
//此处先mark一下,该接口是用来将advisors属性组装为一条拦截链
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
//缓存每个需要被拦截的方法与advisorChainFactory生成的拦截链的映射关系,用于提高性能避免每次都计算链
private transient Map<MethodCacheKey, List<Object>> methodCache;
//指定jdk代理生成的代理对象需要实现的接口,以list中的顺序创建jdk代理
//jdk代理是基于接口的,这个属性的意义在于可以指定对多个接口进行代理,以便代理对象可以转为不同的接口类型
private List<Class<?>> interfaces = new ArrayList<>();
//用于保存所有的Advisor
private List<Advisor> advisors = new ArrayList<>();
//用数组的形式保存Advisor,和上面的advisor属性同步
private Advisor[] advisorArray = new Advisor[0];
public AdvisedSupport() {
this.methodCache = new ConcurrentHashMap<>(32);
}
public AdvisedSupport(Class<?>... interfaces) {
this();
setInterfaces(interfaces);
}
//设置目标对象,这边使用SingletonTargetSource包装了一下
public void setTarget(Object target) {
setTargetSource(new SingletonTargetSource(target));
}
@Override
public void setTargetSource(@Nullable TargetSource targetSource) {
this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE);
}
public void setTargetClass(@Nullable Class<?> targetClass) {
this.targetSource = EmptyTargetSource.forClass(targetClass);
}
//指定AdvisorChainFactory
public void setAdvisorChainFactory(AdvisorChainFactory advisorChainFactory) {
Assert.notNull(advisorChainFactory, "AdvisorChainFactory must not be null");
this.advisorChainFactory = advisorChainFactory;
}
//设置jdk代理对象需要代理的接口
public void setInterfaces(Class<?>... interfaces) {
Assert.notNull(interfaces, "Interfaces must not be null");
this.interfaces.clear();
for (Class<?> ifc : interfaces) {
addInterface(ifc);
}
}
//添加需要代理的接口,和上面setInterfaces方法的区别是该方法会同步清除methodCache中的缓存
public void addInterface(Class<?> intf) {
Assert.notNull(intf, "Interface must not be null");
if (!intf.isInterface()) {
throw new IllegalArgumentException("[" + intf.getName() + "] is not an interface");
}
if (!this.interfaces.contains(intf)) {
this.interfaces.add(intf);
adviceChanged();
}
}
public boolean removeInterface(Class<?> intf) {
return this.interfaces.remove(intf);
}
//获取所有的jdk代理的接口
@Override
public Class<?>[] getProxiedInterfaces() {
return ClassUtils.toClassArray(this.interfaces);
}
//判断某个是否属于代理接口类型
@Override
public boolean isInterfaceProxied(Class<?> intf) {
for (Class<?> proxyIntf : this.interfaces) {
if (intf.isAssignableFrom(proxyIntf)) {
return true;
}
}
return false;
}
//添加Advisor
@Override
public void addAdvisor(Advisor advisor) {
int pos = this.advisors.size();
addAdvisor(pos, advisor);
}
//向advisors中的指定位置添加Advisor
@Override
public void addAdvisor(int pos, Advisor advisor) throws AopConfigException {
if (advisor instanceof IntroductionAdvisor) {
validateIntroductionAdvisor((IntroductionAdvisor) advisor);
}
addAdvisorInternal(pos, advisor);
}
private void addAdvisorInternal(int pos, Advisor advisor) throws AopConfigException {
Assert.notNull(advisor, "Advisor must not be null");
//这边的逻辑就体现了上面ProxyConfig中frozen属性
//如果frozen属性为true,则advisors会被锁定,不能再动态添加Advisor,否则会直接抛异常
if (isFrozen()) {
throw new AopConfigException("Cannot add advisor: Configuration is frozen.");
}
if (pos > this.advisors.size()) {
throw new IllegalArgumentException(
"Illegal position " + pos + " in advisor list with size " + this.advisors.size());
}
this.advisors.add(pos, advisor);
updateAdvisorArray();
adviceChanged();
}
@Override
public boolean removeAdvisor(Advisor advisor) {
int index = indexOf(advisor);
if (index == -1) {
return false;
}
else {
removeAdvisor(index);
return true;
}
}
@Override
public boolean replaceAdvisor(Advisor a, Advisor b) throws AopConfigException {
Assert.notNull(a, "Advisor a must not be null");
Assert.notNull(b, "Advisor b must not be null");
int index = indexOf(a);
if (index == -1) {
return false;
}
removeAdvisor(index);
addAdvisor(index, b);
return true;
}
private void validateIntroductionAdvisor(IntroductionAdvisor advisor) {
advisor.validateInterfaces();
Class<?>[] ifcs = advisor.getInterfaces();
for (Class<?> ifc : ifcs) {
addInterface(ifc);
}
}
//将advisors中的数据转为数组形式到advisorArray
protected final void updateAdvisorArray() {
this.advisorArray = this.advisors.toArray(new Advisor[0]);
}
//添加Advice
@Override
public void addAdvice(Advice advice) throws AopConfigException {
int pos = this.advisors.size();
addAdvice(pos, advice);
}
//向指定下标添加Advice
//你可能会好奇,明明AdvisedSupport中没有保存Advice的地方为什么还有这个方法呢?
@Override
public void addAdvice(int pos, Advice advice) throws AopConfigException {
Assert.notNull(advice, "Advice must not be null");
if (advice instanceof IntroductionInfo) {
addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
}
else if (advice instanceof DynamicIntroductionAdvice) {
throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
//这边将Advice包装为DefaultPointcutAdvisor,进而可以保存到advisors中
addAdvisor(pos, new DefaultPointcutAdvisor(advice));
}
}
//缓存获取当前类中的指定方法对应的拦截链
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
//如果缓存中没有映射则创建当前方法的拦截链并进行缓存
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
protected void adviceChanged() {
this.methodCache.clear();
}
.............
}
如上所示是AdvisedSupport
的核心源码,从中可以看它有如下几个核心功能:
- 维护用户添加的
Advisor
(用户添加的Advice
最终也会被包装为Advisor
(DefaultPointcutAdvisor
)) - 根据
List<Advisor> advisor
属性中各个Advisor
的切点为被代理对象的方法创建对应的拦截链,并且将方法与拦截链的映射关系维护到methodCache
属性中缓存起来
维护Advisor
通过上面对AdvisorSupport
源码的分析可以发现:虽然该类提供了addAdvisor、addAdvice
方法,但其底层只有一个保存Advisor
的属性List<Advisor> advisors
. addAdvisor
方法不用说肯定是直接将Advisor
放到了advisors
属性中,我们重点分析下addAdvice
这个方法:
public void addAdvice(Advice advice) throws AopConfigException {
int pos = this.advisors.size();
addAdvice(pos, advice);
}
public void addAdvice(int pos, Advice advice) throws AopConfigException {
Assert.notNull(advice, "Advice must not be null");
if (advice instanceof IntroductionInfo) {//暂且不考虑IntroductionInfo情况,后面会另起篇章详解
addAdvisor(pos, new DefaultIntroductionAdvisor(advice, (IntroductionInfo) advice));
} else if (advice instanceof DynamicIntroductionAdvice) {//暂且不考虑DynamicIntroductionAdvice情况,后面会另起篇章详解
throw new AopConfigException("DynamicIntroductionAdvice may only be added as part of IntroductionAdvisor");
}
else {
addAdvisor(pos, new DefaultPointcutAdvisor(advice));
}
}
如上图所示addAdvice
方法底层最后都会调用到addAdvice(int pos, Advice advice)
这个方法,可以将Advisor
添加到指定的顺序。暂且只考虑这个方法中else
分支中的情况,首先会将要添加的Advice
包装为DefaultPointcutAdvisor
,然后在将包装好的Advisor
添加到advisors
属性中。
DefaultPointcutAdvisor
这个构造器默认的切点为Pointcut.TRUE
,即拦截所有的方法。
public DefaultPointcutAdvisor(Advice advice) {
this(Pointcut.TRUE, advice);
}
综上所述,使用SpringAop
时无论我们使用@Aspect
注入了切面还是手动注入了Advice
或Advisor
底层都会解析为Advisor
进行处理。前面文章描述过Advisor
的概念,一个Advisor
包含一个切入点Pointcut
和一个建议Advice
。默认情况下AdvisedSupport
会将自定义的Advice
包装为DefaultPointcutAdvisor
, 并且这个Advisor
的切点为Pointcut.TRUE
即对所有的类和方法都有效, 所以调用Advised#addAdvice()
方法会将添加的Advice
转为Advsior
,并且该建议默认对所有类和方法都生效,相当于是一个全局的Advice
.如果想针对某个类或方法做增强,那最好还是调用Advised#addAdvisor()
方法添加我们自定义的Advisor
,这样可以自己指定切入点。
维护方法与拦截器链的映射关系
上面分析AdvisedSupport
源码时,有一个非常关键的方法getInterceptorsAndDynamicInterceptionAdvice
,该方法会为代理方法生成拦截链和缓存该方法与拦截链的映射关系。
public class AdvisedSupport extends ProxyConfig implements Advised {
AdvisorChainFactory advisorChainFactory = new DefaultAdvisorChainFactory();
private transient Map<MethodCacheKey, List<Object>> methodCache;
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
//优先命中缓存取当前方法对应的拦截链
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {//没有命中则为该方法生成拦截链并缓存
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
.......
}
public interface AdvisorChainFactory {
//为方法拦截链,拦截链由MethodInterceptor列表组成
List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass);
}
如上图所示可以看出该方法核心逻辑是通过AdvisorChainFactory
为方法生成拦截链,顾名思义这个接口是生成拦截链(AdvisorChain
), 默认使用的是DefaultAdvisorChainFactory
实现。
DefaultAdvisorChainFactory
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
//AdvisorAdapterRegistry用于保存AdvisorAdapter的注册中心,
//其中AdvisorAdapter是用来将Advisor转为MethodInterceptor的
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//从AdvisedSupport中获取用户定义的所有Advisor
Advisor[] advisors = config.getAdvisors();
//定义一个集合用于保存AdvisorAdapter转换后生成的MethodInterceptor
List<Object> interceptorList = new ArrayList<>(advisors.length);
//从TargetSource中获取方法所在的类的类型
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
//是否存在IntroductionAdvisor类型的Advisor
//IntroductionAdvisor是AOP非常重要的Advisor类型,不常用但是有时很有用,后面单独起篇章剖析
//此处先Mark一下
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
//处理PointcutAdvisor类型的Advisor,即带切入点的Advisor
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//用于处理IntroductionAdvisor类型的Advisor,此处先Mark一下
//后面IntroductionAdvisor篇章再进行剖析
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
//处理其他类型的,例如PrototypePlaceholderAdvisor或自定义的Advisor
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
//用于判断AdvisedSupport中的advisors是否有是IntroductionAdvisor类型的
private static boolean hasMatchingIntroductions(Advisor[] advisors, Class<?> actualClass) {
for (Advisor advisor : advisors) {
if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (ia.getClassFilter().matches(actualClass)) {
return true;
}
}
}
return false;
}
}
如上源码分析所示,getInterceptorsAndDynamicInterceptionAdvice
方法核心功能是 : 首先通过GlobalAdvisorAdapterRegistry.getInstance()
获取到AdvisorAdapterRegistry
, 然后遍历所有的advisors
,使用AdvisorAdapterRegistry
将每个Advisor
包装为 MethodInterceptor
添加到拦截链。到这边可以得出结果 : 拦截链底层是由 MethodInterceptor
组成的。
根据上面的分析可知,DefaultAdvisorChainFactory
核心逻辑会委托给(将Advisor
转为MethodInterceptor
) AdvisorAdapterRegistry
,下面我们就剖析下它。
AdvisorAdapterRegistry
//Advisor适配器注册中心接口
//这是一个SPI接口,任何Spring用户都不能实现
public interface AdvisorAdapterRegistry {
//将Advice转为Avisor. 接口实现至少要实现这个方法
Advisor wrap(Object advice) throws UnknownAdviceTypeException;
//获取当前Advisor包含的MethodInterceptor
//因为MethodInterceptor继承了Advice,所以这边也相当于获取Advisor中包含的Advice
MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException;
//注册AdvisorAdapter到AdvisorAdapterRegistry注册中心中
void registerAdvisorAdapter(AdvisorAdapter adapter);
}
DefaultAdvisorChainFactory
中是通过 GlobalAdvisorAdapterRegistry.getInstance()
获取 AdvisorAdapterRegistry
的。 如下所示可以看出GlobalAdvisorAdapterRegistry
是一个典型的恶汉式
单例模式, 用于获取DefaultAdvisorAdapterRegistry
实现类,这也是SpringAop
提供的唯一默认实现。
public final class GlobalAdvisorAdapterRegistry {
private GlobalAdvisorAdapterRegistry() {}
private static AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
public static AdvisorAdapterRegistry getInstance() {
return instance;
}
static void reset() {
instance = new DefaultAdvisorAdapterRegistry();
}
}
DefaultAdvisorAdapterRegistry
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
//根据Advice的具体类型将其包装为相应类型的Advisor
@Override
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
//如果本身为Advisor,则直接返回即可
if (adviceObject instanceof Advisor) {
return (Advisor) adviceObject;
}
if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
}
Advice advice = (Advice) adviceObject;
//MethodInterceptor类型的Advice将其包装为DefaultPointcutAdvisor
if (advice instanceof MethodInterceptor) {
return new DefaultPointcutAdvisor(advice);
}
//其他类型的Advice则需要检验adapters中的适配器是否支持处理当前类型的Advice
//如果支持则包装为DefaultPointcutAdvisor
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
return new DefaultPointcutAdvisor(advice);
}
}
throw new UnknownAdviceTypeException(advice);
}
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
@Override
public void registerAdvisorAdapter(AdvisorAdapter adapter) {
this.adapters.add(adapter);
}
}
如上图所示,DefaultAdvisorAdapterRegistry
主要是借助 adapters
属性中注册的适配器来完成wrap()、getInterceptors()
实现的,逻辑比较简单。总的来说就是可以将Advice
包装为Advisor
,也可以返回Advisor
包含的建议MethodInterceptor
,这两个功能都会依赖adapters
属性中保存的AdvisorAdapter
来完成。下面我们就剖析下这个AdvisorAdapter
是用来干嘛的。
AdvisorAdapter
public interface AdvisorAdapter {
//判断SpringAop是否支持当前类型的Advice类型
boolean supportsAdvice(Advice advice);
//如果supportsAdvice方法支持当前Advisor中的Advice类型,则可以将Advisor包装为MethodInterceptor
MethodInterceptor getInterceptor(Advisor advisor);
}
如上图UML
图所示,SpringAop
默认提供了三个实现,有没有似曾相似的感觉呢? 前面文章说道SpringAop
是基于AOP联盟
中的标准接口来实现的,而AOP联盟
中只提供了环绕通知建议(MethodInterceptor
)。一般使用SpringAop
时我们还经常用到@Before、@After、@AfterReturning、@AfterThrowing
这些注解来定义前置通知、后置通知、返回值通知、异常通知,以上这些通知是SpringAop
专门为AOP联盟
的Advice
做的扩展建议。
因为AOP联盟
中只支持环绕通知,所以SpringAop
针对这些扩展的通知会使用对应的AdvisorAdapter
将其包装为MethodInterceptor
. 这样这些扩展的通知就可以和环绕通知一样通过AOP联盟
中的MethodInterceptor#invoke()
通用方法运行。
以前置通知的AdvisorAdapter
实现MethodBeforeAdviceAdapter
为例,getInterceptor
方法会将前置通知包装为MethodBeforeAdviceInterceptor
。 它实际上就是 MethodInterceptor
的是一个实现,只不过是在代理方法执行前做了增强而已,在方法执行之后什么都没做,本质上还是一个环绕通知。
//BeforeAdvice继承了Advice接口
public interface MethodBeforeAdvice extends BeforeAdvice {
void before(Method method, Object[] args, @Nullable Object target) throws Throwable;
}
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
ProxyCreatorSupport
public class ProxyCreatorSupport extends AdvisedSupport {
private AopProxyFactory aopProxyFactory;
private final List<AdvisedSupportListener> listeners = new LinkedList<>();
private boolean active = false;
public ProxyCreatorSupport() {
this.aopProxyFactory = new DefaultAopProxyFactory();
}
public ProxyCreatorSupport(AopProxyFactory aopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
public void setAopProxyFactory(AopProxyFactory aopProxyFactory) {
Assert.notNull(aopProxyFactory, "AopProxyFactory must not be null");
this.aopProxyFactory = aopProxyFactory;
}
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}
public void addListener(AdvisedSupportListener listener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.add(listener);
}
public void removeListener(AdvisedSupportListener listener) {
Assert.notNull(listener, "AdvisedSupportListener must not be null");
this.listeners.remove(listener);
}
//生成代理对象
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
private void activate() {
this.active = true;
for (AdvisedSupportListener listener : this.listeners) {
listener.activated(this);
}
}
@Override
protected void adviceChanged() {
super.adviceChanged();
synchronized (this) {
if (this.active) {
for (AdvisedSupportListener listener : this.listeners) {
listener.adviceChanged(this);
}
}
}
}
protected final synchronized boolean isActive() {
return this.active;
}
}
ProxyCreatorSupport
整体比较简单,有两个点重点关注一下。第一个是createAopProxy()
借助AopProxyFactory
生成了SpringAop
代理对象, 第二个是它还留了一个扩展点,当AdvisedSupport
中的配置发生改变后会自动对List<AdvisedSupportListener> listeners
中的监听器进行通知,这有时很有用。下面我们重点看下AopProxyFactory
。
AopProxyFactory
public interface AopProxyFactory {
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;
}
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
//判断是否有指定代理的接口类型
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
SpringAop
提供了一个默认实现 DefaultAopProxyFactory
. 该工厂主要是通过AdvisedSupport
中的代理相关配置决定使用JDK动态代理
还是Cglib代理
生成代理对象。判断条件如下:
- 如果配置了
optimize
或proxyTargetClass
属性为true,并且目标类是一个类而非接口则使用Cglib代理
。如果目标类是一个接口,即使设置了这个两个属性为true也会使用JDK动态代理
- 如果没有配置
optimize
或proxyTargetClass
这两个属性(默认为false),并且有指定要代理的接口类型则会使用JDK代理
。否则会根据目标对象是接口还是类决定使用Cglib代理
还是JDK动态代理
这也解释了为什么在@EnableAspectJAutoProxy
注解中配置proxyTargetClass=true
就可以强制使用cglib代理
,因为一般被代理的都是类。
AopProxy
public interface AopProxy {
Object getProxy();
Object getProxy(@Nullable ClassLoader classLoader);
}
如上所示AopProxy
是对生成代理对象过程的抽象,这个是一个典型的策略模式。从UML
图也可以看出SpringAop
目前只提供了Cglib代理
和JDK动态代理
的支持。至于CglibAopProxy
和JdkDynamicAopProxy
具体生成代理对象的细节,此处先不表,后面文章将基于案例详细剖析。
总结
本文简单剖析了下SpringAop
底层原理过程中涉及到一些比较关键的接口和类。这些类组合到一起的核心功能就是 : 首先将用户定义的Advisor
和Advice
底层都会转为Advisor
并保存在AdvisedSupport中的advisors
中。然后会按照advisors
中顺序为每个需要代理的方法生成一条拦截链,底层生成这个链的过程就是将Advisor
都转为 MethodInterceptor
, 并连接起来组成链。最后返回代理对象,这样调用代理方法时,会对方法进行增强,所谓增强就是在各个拦截链中做了想做的事情(Advice
).
其实分析完这些关键的类,SpringAop
的大致流程也就搞明白了。下篇文章将结合一个案例剖析下具体的代理过程细节。