紧接着上文,在获取了所有对应 Bean 的增强器后,便可以进行代理的创建了。
回到 postProcesssAfterIntialization 方法中,在我们分析完 getAdvicesAndAdvisorsForBean()
后,还有一个 createProxy 方法。
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
//指定自动代理Bean的原始目标类 AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
//获取当前类中相关属性
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
// 决定对于给定的bean是否应该使用targetClass而不是它的接口代理,
// 检査 proxyTargetClass 设置以及 preserveTargetClass 属性
if (this.shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
this.evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = this.buildAdvisors(beanName, specificInterceptors);
// 加入增强器
proxyFactory.addAdvisors(advisors);
// 设置要代理的目标类
proxyFactory.setTargetSource(targetSource);
// 定制代理
this.customizeProxyFactory(proxyFactory);
// 用来控制代理工厂被配置之后,是否还允许修改通知。
// 缺省值是false (即在代理被配置之后,不允许修改代理的配置)。
proxyFactory.setFrozen(this.freezeProxy);
if (this.advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//真正创建代理的方法
return proxyFactory.getProxy(this.getProxyClassLoader());
}
对于代理类的创建及处理,Spring 委托给了 ProxyFactory 去处理,而在此函数中主要是对 ProxyFactory 的初始化操作,进而对真正的创建代理做准备,这些初始化操作包括以下内容:
- 获取当前类中的属性。
- 添加代理接口。
- 封装 Advisor 并加入到 ProxyFactory 中。
- 设置要代理的类。
- customizeProxyFactory 函数定制代理。
- 进行获取代理操作。
封装 Advisor
其中,封装 Advisor 并加入到 ProxyFactory 中以及创建代理工作量比较大,所以我们就来看一下 buildAdvisors()
。
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
Advisor[] commonInterceptors = this.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));
}
}
}
int i;
if (this.logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
i = specificInterceptors != null ? specificInterceptors.length : 0;
this.logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors + " common interceptors and " + i + " specific interceptors");
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for(i = 0; i < allInterceptors.size(); ++i) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
上述方法中会涉及到适配器模式的应用,我们转到 DefaultAdvisorAdapterRegistry 类中,查看其 wrap 方法。
public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
if (adviceObject instanceof Advisor) {
return (Advisor)adviceObject;
} else if (!(adviceObject instanceof Advice)) {
throw new UnknownAdviceTypeException(adviceObject);
} else {
Advice advice = (Advice)adviceObject;
if (advice instanceof MethodInterceptor) {
//如果是MethodInterceptor类型,则封装为DefaultPointcutAdvisor
return new DefaultPointcutAdvisor(advice);
} else {
Iterator var3 = this.adapters.iterator();
//如果存在Advisor的适配器则也需要进行封装
AdvisorAdapter adapter;
do {
if (!var3.hasNext()) {
throw new UnknownAdviceTypeException(advice);
}
adapter = (AdvisorAdapter)var3.next();
} while(!adapter.supportsAdvice(advice));
return new DefaultPointcutAdvisor(advice);
}
}
}
关于这一部分,我进行了调试追踪,发现该方法的结果如下:
对此我有一个疑问:在创建代理之前,即执行 getAdvicesAndAdvisorsForBean()
方法后,我们获取到的结果除了头部对象是 DefaultPointcutAdvisor 类型,其他三个是 Advisor 的实现类 InstantiationModelAwarePointcutAdvisorImpl 类型,执行 wrap 方法中 adviceObject instanceof Advisor
结果都为 true。那么该方法主要是针对什么情景下使用的呢?如果有大神知晓,请不吝赐教。
创建代理
封装完 Advisor 之后就准备进行代理的创建,这也是解析过程中最重要的一步。
public Object getProxy(@Nullable ClassLoader classLoader) {
return this.createAopProxy().getProxy(classLoader);
}
在上面的 getProxy 方法中 createAopProxy 方法,其实现是在 ProxyCreatorSupport 中,其定义如下:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
this.activate();
}
return this.getAopProxyFactory().createAopProxy(this);
}
private void activate() {
this.active = true;
Iterator var1 = this.listeners.iterator();
while(var1.hasNext()) {
//启动监听器
AdvisedSupportListener listener = (AdvisedSupportListener)var1.next();
listener.activated(this);
}
}
再次跳转到 DefaultAopProxyFactory 类中,查看 createAopProxy 方法。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!config.isOptimize() && !config.isProxyTargetClass() && !this.hasNoUserSuppliedProxyInterfaces(config)) {
return new JdkDynamicAopProxy(config);
} else {
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.");
} else {
//手动设置创建Cglib代理类后,如果目标bean是一个接口,则创建jdk代理类
return (AopProxy)(!targetClass.isInterface() && !Proxy.isProxyClass(targetClass) ? new ObjenesisCglibAopProxy(config) : new JdkDynamicAopProxy(config));
}
}
}
我们在 代理模式一文中知道 Spring 的代理是通过 JDKProxy 的实现或 CglibProxy 实现。Spring 是如何选取的呢?
从 if 中的判断条件可以看到3个方面影响着 Spring 的判断。
- optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略,除非完全了解AOP代理如何处理优化,否则不推荐用户使用这个设置。目前这个属性仅用于CGLIB 代理,对于JDK动态代理(缺省代理)无效。
- proxyTargetClass:这个属性为true时,目标类本身被代理而不是目标类的接口。如果这个属性值被设为true,CGLIB代理将被创建,设置方式:。
- hasNoUserSuppliedProxylnterfaces:是否存在代理接口
下面是对JDK与Cglib方式的总结。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP。
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP。
- 如果目标对象没有实现了接口,必须采用CGLIB库,Spring会自动在JDK动态代理 和CGLIB之间转换。
如何强制使用CGLIB实现AOP?
(1)添加 CGLIB 库,Spring_HOME/cglib/*.jar。
(2)在 Spring 配置文件中加人<aop:aspectj-autoproxy proxy-target-class=“true”/>。
JDK 动态代理和 CGLIB 字节码生成的区别?
JDK 动态代理只能对实现了接口的类生成代理,而不能针对类。
CGLIB 是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成 final。
获取代理
本文主要介绍 JDK 动态代理类的实现,在此之前,有必要熟悉一下 JDK 代理使用示例,请看我以前的博文 代理模式。
Spring 的 AOP 实现其实也是用了 Proxy和InvocationHandler 这两个东西的。
我们再次来回顾一下使用 JDK 代理的方式,在整个创建过程中,对于 InvocationHandler 的创建是最为核心的,关于 Proxy 的获取方法其实也可以放在 InvocationHandler 的实现类中。这样总结为3个函数:
- 构造函数,传入代理的对象。
- invoke 方法,此方法用于实现 AOP 增强的所有逻辑。
- getProxy 方法,即
Proxy.newProxyInstance()
方法,必不可少。
接下来我们学习一下 JdkDynamicAopProxy 的源码。
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
Assert.notNull(config, "AdvisedSupport must not be null");
if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
throw new AopConfigException("No advisors and no TargetSource specified");
} else {
this.advised = config;
}
}
public Object getProxy() {
return this.getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
Class[] var2 = proxiedInterfaces;
int var3 = proxiedInterfaces.length;
for(int var4 = 0; var4 < var3; ++var4) {
Class<?> proxiedInterface = var2[var4];
Method[] methods = proxiedInterface.getDeclaredMethods();
Method[] var7 = methods;
int var8 = methods.length;
for(int var9 = 0; var9 < var8; ++var9) {
Method method = var7[var9];
if (AopUtils.isEqualsMethod(method)) {
this.equalsDefined = true;
}
if (AopUtils.isHashCodeMethod(method)) {
this.hashCodeDefined = true;
}
if (this.equalsDefined && this.hashCodeDefined) {
return;
}
}
}
}
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
Integer var8;
try {
//equals方法判断
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
Boolean var18 = this.equals(args[0]);
return var18;
}
//hash方法判断
if (this.hashCodeDefined || !AopUtils.isHashCodeMethod(method)) {
if (method.getDeclaringClass() == DecoratingProxy.class) {
Class var17 = AopProxyUtils.ultimateTargetClass(this.advised);
return var17;
}
Object retVal;
if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
}
// 如果 expose-proxy 属性为 true,则暴露代理对象
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
Class<?> targetClass = target != null ? target.getClass() : null;
// 获取适合当前方法的拦截器
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
if (chain.isEmpty()) {// 如果拦截器链为空,则直接执行目标方法
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
// 通过反射执行目标方法
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// 创建一个方法调用器,并将拦截器链传入其中
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行拦截器链
retVal = invocation.proceed();
}
// 获取方法返回值类型
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// 如果方法返回值为 this,即 return this; 则将代理对象 proxy 赋值给 retVal
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { // 如果返回值类型为基础类型,比如 int,long 等,当返回值为 null,抛出异常
throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
}
Object var12 = retVal;
return var12;
}
var8 = this.hashCode();
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
return var8;
}
我们总结一下 invoke 方法的执行流程,如下:
- 检测 expose-proxy 是否为true,若为true,则暴露代理对象。
- 获取适合当前方法的拦截器。
- 如果拦截器链为空,则直接通过反射执行目标方法。
- 如果拦截器链不为空,则创建 ReflectiveMethodInvocation 对象。
- 调用 ReflectiveMethodInvocation 对象的 proceed()方法启动拦截器链。
- 处理返回值,并返回该值。
以上六个步骤,我们重点关注第2步和第5步的处理逻辑,下面先来分析获取拦截器链的过程。
获取目标方法的拦截器
getInterceptorsAndDynamicInterceptionAdvice()
方法用来获取目标方法的拦截器,这是我们在 Spring AOP 中第一次提到拦截器,大家可能在别的地方使用过,拦截器用于对目标方法的调用进行拦截的一种工具。拦截器与我们之前获取的增强器有什么关系呢?带着这样的疑问,我们来分析 AdvisedSupport 类中的 getInterceptorsAndDynamicInterceptionAdvice 源码。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
AdvisedSupport.MethodCacheKey cacheKey = new AdvisedSupport.MethodCacheKey(method);
// 从缓存中获取
List<Object> cached = (List)this.methodCache.get(cacheKey);
// 缓存为空,则进行下一步处理
if (cached == null) {
// 获取所有的拦截器
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);
// 存入缓存
this.methodCache.put(cacheKey, cached);
}
return cached;
}
其中比较核心的方法是 getInterceptorsAndDynamicInterceptionAdvice()
,在 DefaultAdvisorChainFactory 类中实现。
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
// registry 为 DefaultAdvisorAdapterRegistry 类型
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//获取目标方法对应的增强器
Advisor[] advisors = config.getAdvisors();
//声明拦截器列表
List<Object> interceptorList = new ArrayList(advisors.length);
//目标类
Class<?> actualClass = targetClass != null ? targetClass : method.getDeclaringClass();
Boolean hasIntroductions = null;
Advisor[] var9 = advisors;
int var10 = advisors.length;
// 遍历增强器列表
for(int var11 = 0; var11 < var10; ++var11) {
Advisor advisor = var9[var11];
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor)advisor;
//调用 ClassFilter 对 bean 类型进行匹配,无法匹配则说明当前增强器不适用于当前bean
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) {
// 将 advisor 中的 advice 转成相应的拦截器
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
// 若 isRuntime 返回 true,则表明 MethodMatcher 要在运行时做一些检测
if (mm.isRuntime()) {
MethodInterceptor[] var17 = interceptors;
int var18 = interceptors.length;
for(int var19 = 0; var19 < var18; ++var19) {
MethodInterceptor interceptor = var17[var19];
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
} else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
} else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor)advisor;
// IntroductionAdvisor 类型的增强器,仅需进行类级别的匹配即可
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
} else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList(3);
Advice advice = advisor.getAdvice();
//若 advice 是 MethodInterceptor 类型的,直接添加到 interceptors 中即可
//比如 AspectJAfterAdvice 就实现了 MethodInterceptor 接口
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor)advice);
}
Iterator var4 = this.adapters.iterator();
//对于 AspectJMethodBeforeAdvice 等类型的通知,由于没有实现 MethodInterceptor接口,所以这里需要通过适配器进行转换
//比如AspectJMethodBeforeAdvice类型会被转换为MethodBeforeAdviceInterceptor
while(var4.hasNext()) {
AdvisorAdapter adapter = (AdvisorAdapter)var4.next();
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
} else {
return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[0]);
}
}
以上便是获取拦截器的过程,不过好在逻辑不是很复杂,这里简单总结一下。
- 从缓存中获取目标方法的拦截器链。
- 若缓存为中,则调用 getInterceptorsAndDynamicInterceptionAdvice 获取拦截器链。
- 遍历增强器列表,如果是 PointcutAdvisor 类型的增强器,需要调用增强器所持有的切点对类和方法进行匹配,匹配成功说明应向当前方法织入通知逻辑卷。
- 调用 getInterceptors 方法对非 MethodInterceptor 类型的通知转换为拦截器。
- 返回拦截器链,并存入缓存中。
由于 Spring 中涉及过多的拦截器,增强器,增强方法等方式来对逻辑进行增强,AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice 这几个增强器都实现了 MethodInterceptor 接口,AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice 并没有实现 MethodInterceptor 接口,因此AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice不能满足MethodInterceptor 接口中的invoke方法,所以这里使用适配器模式将AspectJMethodBeforeAdvice 和 AspectJAfterReturningAdvice 转化成能满足需求的MethodInterceptor 实现类。
遍历 adapters,通过 adapter.supportsAdvice(advice)
找到 advice 对应的适配器,adapter.getInterceptor(advisor)
将 advisor 转化成对应的 interceptor。
比如 AspectJMethodBeforeAdvice ,我们查看一下其对应的拦截器。
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;
}
public Object invoke(MethodInvocation mi) throws Throwable {
//执行前置通知逻辑
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//调用proceed执行下一个拦截器
return mi.proceed();
}
}
代码比较简单,这里就不多说了。
现在我们已经获得了拦截器链,那么接下来要做的就是启动拦截器,我们继续向下分析代码,看看 Spring 是如何启动拦截器链的。
启动拦截器链
回到 JdkDynamicAopProxy 中,继续向下学习。我们先来说说 ReflectiveMethodInvocation,该类贯穿于拦截器链执行的始终,是非常核心的内容。该类的 proceed 方法用于启动拦截器链,下面我们看下该方法。
public Object proceed() throws Throwable {
//判断是不是所有的interceptor(也可以想像成advisor)都被执行完了。
// 拦截器链中的最后一个拦截器执行完后,即可执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
// 如果Interceptor没有被全部执行完,就取出要执行的Interceptor,并执行。
// currentInterceptorIndex先自增
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 如果Interceptor是PointCut类型
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
Class<?> targetClass = this.targetClass != null ? this.targetClass : this.method.getDeclaringClass();
// 如果当前方法符合Interceptor的PointCut限制,就执行Interceptor,如果不符合,则跳过并执行下一个Interceptor
return dm.methodMatcher.matches(this.method, targetClass, this.arguments) ? dm.interceptor.invoke(this) : this.proceed();
} else {
// 如果Interceptor不是PointCut类型,就直接执行Interceptor里面的增强。
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
从上述代码可知,ReflectiveMethodInvocation 中的 currentInterceptorIndex 充当拦截器链调用的计数器,记录着当前调用链接的位置 proceed 根据 currentInterceptorIndex 来确定当前应执行哪个拦截器,并在调用拦截器的 invoke 方法时,将自己作为参数传给该方法。 前置通知会在目标方法执行前执行,我们在前面也看了前置拦截器的源码,这里看一下后置拦截器的源码,如下:
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable {
public AspectJAfterAdvice(Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
super(aspectJBeforeAdviceMethod, pointcut, aif);
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object var2;
try {
var2 = mi.proceed();
} finally {
//调用后置通知逻辑
this.invokeAdviceMethod(this.getJoinPointMatch(), (Object)null, (Throwable)null);
}
return var2;
}
public boolean isBeforeAdvice() {
return false;
}
public boolean isAfterAdvice() {
return true;
}
}
因为后置通知是在目标方法返回后执行,所以 AspectJAfterAdvice 先调用 mi.proceed()
执行下一个拦截器逻辑,等下一个拦截器返回后,最后执行后置通知逻辑。如果大家不理解,我根据调试过程画了一张图,结合初识Spring AOP一文中的案例,其中包含前置通知、后置通知和环绕通知,执行流程如下:
关于执行过程中第一个拦截器 ExposeInvocationInterceptor,需要讲解一下。在Spring AOP创建代理之获取增强器文章末尾中,在介绍 extendAdvisors 方法时,有提及到拓展增强器列表,具体意图当时没有讲述,待会进行补充说明。这里再贴一下 extendAdvisors 方法的源码,如下:
protected void extendAdvisors(List<Advisor> candidateAdvisors) {
AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
}
public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
Iterator var2 = advisors.iterator();
while(var2.hasNext()) {
Advisor advisor = (Advisor)var2.next();
//检测 advisors 列表中是否存在 AspectJ 类型的 Advisor 或 Advice
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
break;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
//向 advisors 列表的首部添加 ExposeInvocationInterceptor.ADVISOR
advisors.add(0, ExposeInvocationInterceptor.ADVISOR);
return true;
}
}
return false;
}
如上,extendAdvisors 所调用的方法会向通知器列表首部添加 ExposeInvocationInterceptor.ADVISOR。现在我们再来看看 ExposeInvocationInterceptor 的源码,如下:
public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
public static final ExposeInvocationInterceptor INSTANCE = new ExposeInvocationInterceptor();
public static final Advisor ADVISOR;
private static final ThreadLocal<MethodInvocation> invocation;
public static MethodInvocation currentInvocation() throws IllegalStateException {
MethodInvocation mi = (MethodInvocation)invocation.get();
if (mi == null) {
throw new IllegalStateException("No MethodInvocation found: Check that an AOP invocation is in progress, and that the ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor!");
} else {
return mi;
}
}
private ExposeInvocationInterceptor() {
}
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = (MethodInvocation)invocation.get();
// 将 mi 设置到 ThreadLocal 中
invocation.set(mi);
Object var3;
try {
var3 = mi.proceed();
} finally {
invocation.set(oldInvocation);
}
return var3;
}
public int getOrder() {
return -2147483647;
}
private Object readResolve() {
return INSTANCE;
}
static {
// 创建 DefaultPointcutAdvisor 匿名对象
ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {
public String toString() {
return ExposeInvocationInterceptor.class.getName() + ".ADVISOR";
}
};
invocation = new NamedThreadLocal("Current AOP method invocation");
}
}
如上,ExposeInvocationInterceptor.ADVISOR 经过 registry.getInterceptors()
方法(前面已分析过)处理后,即可得到 ExposeInvocationInterceptor。ExposeInvocationInterceptor 的作用是用于暴露 MethodInvocation 对象到 ThreadLocal 中,其名字也体现出了这一点。
关于拦截器链的执行流程,其实可以看成是一个递归的调用过程,通过 ReflectiveMethodInvocation 类中 Proceed 方法递归调用,顺序执行拦截器链中 AspectJAfterAdvice、 AspectJAroundAdvice 、 MethodBeforeAdviceInterceptor这几个拦截器,在拦截器中反射调用通知方法。说的再多,不如实际调试理解的透彻,建议不懂的朋友将这几个拦截器中的 invoke 方法都打上断点,自己亲自执行一遍。
最后说一下目标方法的执行,看一看发生在何处。
执行目标方法
在 proceed 方法中当 currentInterceptorIndex 计数满足条件时,将会执行 invokeJoinpoint 方法,即执行目标方法。我们来看一下源码。
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable {
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
} catch (InvocationTargetException var4) {
throw var4.getTargetException();
} catch (IllegalArgumentException var5) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", var5);
} catch (IllegalAccessException var6) {
throw new AopInvocationException("Could not access method [" + method + "]", var6);
}
}
目标方法就是通过反射执行的,比较简单,在调试的过程中也可以发现。
总结
至此,关于 Spring AOP 源码的学习终于要结束了,关于 Spring 源码的学习大概花了40天的时间,进度比较慢,为此也没怎么学习别的事情。不过结局是好的,通过这次学习还是有很大的收获和成就感。由于技术尚浅,某些部分讲的不够透彻,或者有问题的,请大家见谅,如果可以的话希望能够指正一下,这里先说声谢谢啦。