前言
会更新AOP 系列源码文章 主要更新目录
篇幅问题 会分章程更新
方法增强
main() 函数中调用用户方法,会进入代理对象的 invoke 方法
JdkDynamicAopProxy 类中的 invoke 方法是真正执行代理方法
// proxy:代理对象,method:目标对象的方法,args:目标对象方法对应的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
// advised 就是初始化 JdkDynamicAopProxy 对象时传入的变量
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
// 条件成立说明代理类实现的接口没有定义 equals 方法,并且当前 method 调用 equals 方法,
// 就调用 JdkDynamicAopProxy 提供的 equals 方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
return equals(args[0]);
} //.....
Object retVal;
// 需不需要暴露当前代理对象到 AOP 上下文内
if (this.advised.exposeProxy) {
// 【把代理对象设置到上下文环境】
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 根据 targetSource 获取真正的代理对象
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 查找【适合该方法的增强】,首先从缓存中查找,查找不到进入主方法【下文详解】
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 拦截器链是空,说明当前 method 不需要被增强
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 有匹配当前 method 的方法拦截器,要做增强处理,把方法信息封装到方法调用器里
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())) {
// 如果目标方法返回目标对象,这里做个普通替换返回代理对象
retVal = proxy;
}
// 返回执行的结果
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
// 如果允许了提前暴露,这里需要设置为初始状态
if (setProxyContext) {
// 当前代理对象已经完成工作,【把原始对象设置回上下文】
AopContext.setCurrentProxy(oldProxy);
}
}
}
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass):查找适合该方法的增强,首先从缓存中查找,获取通知时是从全部增强中获取适合当前类的,这里是从当前类的中获取适合当前方法的增强
-
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance()
:向容器注册适配器,可以将非 Advisor 类型的增强,包装成为 Advisor,将 Advisor 类型的增强提取出来对应的 MethodInterceptor-
instance = new DefaultAdvisorAdapterRegistry()
:该对象向容器中注册了 MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter 三个适配器 -
Advisor 中持有 Advice 对象
public interface Advisor { Advice getAdvice(); }
-
-
advisors = config.getAdvisors()
:获取 ProxyFactory 内部持有的增强信息 -
interceptorList = new ArrayList<>(advisors.length)
:拦截器列表有 5 个,1 个 ExposeInvocation和 4 个增强器 -
actualClass = (targetClass != null ? targetClass : method.getDeclaringClass())
:真实的目标对象类型 -
Boolean hasIntroductions = null
:引介增强,不关心 -
for (Advisor advisor : advisors)
:遍历所有的 advisor 增强 -
if (advisor instanceof PointcutAdvisor)
:条件成立说明当前 Advisor 是包含切点信息的,进入匹配逻辑pointcutAdvisor = (PointcutAdvisor) advisor
:转成可以获取到切点信息的接口if(config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass))
:当前代理被预处理,或者当前被代理的 class 对象匹配当前 Advisor 成功,只是 class 匹配成功-
mm = pointcutAdvisor.getPointcut().getMethodMatcher()
:获取切点的方法匹配器,不考虑引介增强 -
match = mm.matches(method, actualClass)
:静态匹配成功返回 true,只关注于处理类及其方法,不考虑参数 -
if (match)
:如果静态切点检查是匹配的,在运行的时候才进行动态切点检查,会考虑参数匹配(代表传入了参数)。如果静态匹配失败,直接不需要进行参数匹配,提高了工作效率interceptors = registry.getInterceptors(advisor)
:提取出当前 advisor 内持有的 advice 信息-
Advice advice = advisor.getAdvice()
:获取增强方法 -
if (advice instanceof MethodInterceptor)
:当前 advice 是 MethodInterceptor 直接加入集合 -
for (AdvisorAdapter adapter : this.adapters)
:遍历三个适配器进行匹配(初始化时创建的),匹配成功创建对应的拦截器返回,以 MethodBeforeAdviceAdapter 为例if (adapter.supportsAdvice(advice))
:判断当前 advice 是否是对应的 MethodBeforeAdviceinterceptors.add(adapter.getInterceptor(advisor))
:条件成立就往拦截器链中添加 advisoradvice = (MethodBeforeAdvice) advisor.getAdvice()
:获取增强方法return new MethodBeforeAdviceInterceptor(advice)
:封装成 MethodBeforeAdviceInterceptor 返回
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm))
:向拦截器链添加动态匹配器interceptorList.addAll(Arrays.asList(interceptors))
:将当前 advisor 内部的方法拦截器追加到 interceptorList -
-
-
interceptors = registry.getInterceptors(advisor)
:进入 else 的逻辑,说明当前 Advisor 匹配全部 class 的全部 method,全部加入到 interceptorList -
return interceptorList
:返回 method 方法的拦截器链
retVal = invocation.proceed():拦截器链驱动方法
-
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1)
:条件成立说明方法拦截器全部都已经调用过了(index 从 - 1 开始累加),接下来需要执行目标对象的目标方法return invokeJoinpoint()
:调用连接点(目标)方法 -
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex)
:获取下一个方法拦截器 -
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher)
:需要运行时匹配if (dm.methodMatcher.matches(this.method, targetClass, this.arguments))
:判断是否匹配成功return dm.interceptor.invoke(this)
:匹配成功,执行方法return proceed()
:匹配失败跳过当前拦截器
-
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this)
:一般方法拦截器都会执行到该方法,此方法内继续执行 proceed() 完成责任链的驱动,直到最后一个 MethodBeforeAdviceInterceptor 调用前置通知,然后调用 mi.proceed(),发现是最后一个拦截器就直接执行连接点(目标方法),return 到上一个拦截器的 mi.proceed() 处,依次返回到责任链的上一个拦截器执行通知方法
图示先从上往下建立链,然后从下往上依次执行,责任链模式
-
正常执行:(环绕通知)→ 前置通知 → 目标方法 → 后置通知 → 返回通知
-
出现异常:(环绕通知)→ 前置通知 → 目标方法 → 后置通知 → 异常通知
-
MethodBeforeAdviceInterceptor 源码:
public Object invoke(MethodInvocation mi) throws Throwable { // 先执行通知方法,再驱动责任链 this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); // 开始驱动目标方法执行,执行完后返回到这,然后继续向上层返回 return mi.proceed(); }
AfterReturningAdviceInterceptor 源码:没有任何异常处理机制,直接抛给上层
public Object invoke(MethodInvocation mi) throws Throwable { // 先驱动责任链,再执行通知方法 Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; }
AspectJAfterThrowingAdvice 执行异常处理:
public Object invoke(MethodInvocation mi) throws Throwable { try { // 默认直接驱动责任链 return mi.proceed(); } catch (Throwable ex) { // 出现错误才执行该方法 if (shouldInvokeOnThrowing(ex)) { invokeAdviceMethod(getJoinPointMatch(), null, ex); } throw ex; } }
本文正在参加「金石计划 . 瓜分6万现金大奖」