本文详细介绍Spring AOP的执行阶段流程。
Cglib代理的代理拦截逻辑在DynamicAdvisedInterceptor中,JDK代理的拦截逻辑在JdkDynamicAopProxy中,本文将从这两个类入手分析Spring AOP的执行阶段流程。
DynamicAdvisedInterceptor
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object intercept(
Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// ...
}
intercept方法核心逻辑
Cglib实现的动态代理都是通过这个类的intercept方法进行拦截的:
- 该类在创建时需要传入一个advised对象,这个对象内部封装着所有的Advisor集
- 将advised对象中封装的Advisor集转换成MethodInterceptor链
- 构建一个CglibMethodInvocation并执行拦截器链
代码:
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// 1. 将Advisor集转换成MethodInterceptor链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
} else {
// We need to create a method invocation...
// 2. 构建一个CglibMethodInvocation并执行拦截器链
retVal = new CglibMethodInvocation(
proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
} finally {
// 略
}
Advisor集
我们先debug看一下advised对象的Advisor集:
可以看到advisors的每个对象封装了如下通知对象:
- before - AspectJMethodBeforeAdvice对象
- after - AspectJAfterAdvice对象
- afterReturn - AspectJAfterReturningAdvice对象
- afterThrowing - AspectJAfterThrowingAdvice对象
getInterceptorsAndDynamicInterceptionAdvice方法
将advised对象的Advisor集转为MethodInterceptor集:
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;
}
// advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
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;
for (Advisor advisor : advisors) {
// AOP执行的是这个分支,我们重点看这个分支
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
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) {
// 这里把Advisor对象转为MethodInterceptor集
// 代码不复杂,此处不做记录了
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// 执行这个分支
// 使用InterceptorAndDynamicMethodMatcher类型封装表示在后续执行是仍需要进行一次匹配
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
} else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
} else if (advisor instanceof IntroductionAdvisor) {
// 略
} else {
// 略
}
}
return interceptorList;
}
转换之后的chain集合里面每个元素都是InterceptorAndDynamicMethodMatcher对象,该对象里面封装着MethodInterceptor实现类对象:
在此记录一下类型转换对应关系:
通知类型 | Advice类型 | MethodInterceptor类型 |
---|---|---|
before | AspectJMethodBeforeAdvice | MethodBeforeAdviceInterceptor |
after | AspectJAfterAdvice | |
afterReturn | AspectJAfterReturningAdvice | AfterReturningAdviceInterceptor |
afterThrowing | AspectJAfterThrowingAdvice |
创建CglibMethodInvocation执行拦截链
retVal =
new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)
.proceed();
CglibMethodInvocation的proceed方法:
public Object proceed() throws Throwable {
// 此分支匹配时,调用目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass =
(this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
// 此处又做了一次切入点匹配
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
// 执行拦截器方法
return dm.interceptor.invoke(this);
} else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
} else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
MethodInterceptor实现类
此处简单介绍几个MethodInterceptor实现类:
- ExposeInvocationInterceptor
- MethodBeforeAdviceInterceptor
- AspectJAfterAdvice
- AfterReturningAdviceInterceptor
- AspectJAfterThrowingAdvice
ExposeInvocationInterceptor
这个拦截器没有实际用处,只是为了把MethodInvocation放到thread local上,便于在代码中获取并使用。下面是API文档:
Interceptor that exposes the current MethodInvocation as a thread-local object. We occasionally need to do this; for example, when a pointcut (e.g. an AspectJ expression pointcut) needs to know the full invocation context.
Don’t use this interceptor unless this is really necessary. Target objects should not normally know about Spring AOP, as this creates a dependency on Spring API. Target objects should be plain POJOs as far as possible.
If used, this interceptor will normally be the first in the interceptor chain.
public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = invocation.get();
invocation.set(mi);
try {
return mi.proceed();
} finally {
invocation.set(oldInvocation);
}
}
这个类对外提供一个静态方法,用于获取当前线程上的MethodInvocation对象:
private static final ThreadLocal<MethodInvocation> invocation =
new NamedThreadLocal<>("Current AOP method invocation");
public static MethodInvocation currentInvocation() throws IllegalStateException {
MethodInvocation mi = invocation.get();
if (mi == null) {
throw new IllegalStateException("No MethodInvocation found");
}
return mi;
}
MethodBeforeAdviceInterceptor
执行before切面方法:
public Object invoke(MethodInvocation mi) throws Throwable {
// 调用before切面方法,里面的代码不展开记录了
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
// 继续执行调用链
// 此处就回到了CglibMethodInvocation的proceed方法
// 此时currentInterceptorIndex已经指向下一个Interceptor
return mi.proceed();
}
AspectJAfterAdvice
执行after切面方法:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 先执行调用链
return mi.proceed();
} finally {
// 在finally中调用after切面方法
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
AfterReturningAdviceInterceptor
执行afterReturn切面方法:
public Object invoke(MethodInvocation mi) throws Throwable {
// 先执行调用链
Object retVal = mi.proceed();
// 执行afterReturn切面方法
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
AspectJAfterThrowingAdvice
执行afterThrow切面方法:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
// 先执行调用链
return mi.proceed();
} catch (Throwable ex) {
// 执行afterReturn切面方法
if (shouldInvokeOnThrowing(ex)) {
invokeAdviceMethod(getJoinPointMatch(), null, ex);
}
throw ex;
}
}
模拟MethodInvocation调用链
源代码里面的MethodInvocation调用链代码不是很好理解,为了方便理解,此处写了一段类似的代码,如下:
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 模拟spring aop调用链
*/
public class SpringAopAdvisorMain {
/**
* 模拟目标业务类
*/
public static class Service {
public String doService() {
System.out.println("Service.doService()");
return "ok";
// throw new RuntimeException("error");
}
}
/**
* 模拟AOP调用链
*/
public static class Invocation {
// 拦截器集
private final List<AdvisorInterceptor> interceptors;
// 索引标识
private int index = -1;
// aop目标对象
private final Object proxyObject;
// aop目标方法
private final Method proxyMethod;
public Invocation(
List<AdvisorInterceptor> interceptors, Object proxyObject,
Method proxyMethod) {
this.interceptors = interceptors;
this.proxyObject = proxyObject;
this.proxyMethod = proxyMethod;
}
/**
* AOP调用链处理入口
*/
public Object process() throws Exception {
// 当所有拦截器都入调用栈之后,调用目标业务方法
if (index == interceptors.size() - 1) {
return this.proxyMethod.invoke(this.proxyObject);
} else {
// 调用拦截器方法
AdvisorInterceptor interceptor = interceptors.get(++index);
return interceptor.process(this);
}
}
}
/**
* 模拟AOP调用链拦截器
*/
interface AdvisorInterceptor {
Object process(Invocation invocation) throws Exception;
}
/**
* 纯粹是为了实验显示name值才创建了这个抽象类
*/
public static abstract class AbstractAdvisorInterceptor implements AdvisorInterceptor {
protected String name;
public AbstractAdvisorInterceptor(String name) {
this.name = name;
}
}
/**
* 前置通知拦截器
*/
public static class BeforeAdvisorInterceptor extends AbstractAdvisorInterceptor {
public BeforeAdvisorInterceptor(String name) {
super(name);
}
@Override
public Object process(Invocation invocation) throws Exception {
this.before();
return invocation.process();
}
private void before() {
System.out.printf(">>> %s.%s\n", name, "before");
}
}
/**
* 返回通知拦截器
*/
public static class AfterReturnAdvisorInterceptor extends AbstractAdvisorInterceptor {
public AfterReturnAdvisorInterceptor(String name) {
super(name);
}
@Override
public Object process(Invocation invocation) throws Exception {
Object ret = invocation.process();
this.afterReturn();
return ret;
}
private void afterReturn() {
System.out.printf(">>> %s.%s\n", name, "afterReturn");
}
}
/**
* 异常通知拦截器
*/
public static class AfterThrowingAdvisorInterceptor extends AbstractAdvisorInterceptor {
public AfterThrowingAdvisorInterceptor(String name) {
super(name);
}
@Override
public Object process(Invocation invocation) throws Exception {
try {
return invocation.process();
} catch (Exception e) {
this.afterThrowing();
throw e;
}
}
private void afterThrowing() {
System.out.printf(">>> %s.%s\n", name, "afterThrowing");
}
}
/**
* 后置通知拦截器
*/
public static class AfterAdvisorInterceptor extends AbstractAdvisorInterceptor {
public AfterAdvisorInterceptor(String name) {
super(name);
}
@Override
public Object process(Invocation invocation) throws Exception {
try {
return invocation.process();
} finally {
this.after();
}
}
private void after() {
System.out.printf(">>> %s.%s\n", name, "after");
}
}
public static void main(String[] args) throws Exception {
// 创建拦截器
List<AdvisorInterceptor> interceptors = new ArrayList<>();
interceptors.add(new BeforeAdvisorInterceptor("before1"));
interceptors.add(new AfterAdvisorInterceptor("after1"));
interceptors.add(new AfterReturnAdvisorInterceptor("afterReturn1"));
interceptors.add(new AfterThrowingAdvisorInterceptor("afterThrowing1"));
interceptors.add(new BeforeAdvisorInterceptor("before2"));
interceptors.add(new AfterAdvisorInterceptor("after2"));
interceptors.add(new AfterReturnAdvisorInterceptor("afterReturn2"));
interceptors.add(new AfterThrowingAdvisorInterceptor("afterThrowing2"));
// 目标业务层方法
Service service = new Service();
Method method = Service.class.getMethod("doService");
// 调用链
Invocation invocation = new Invocation(interceptors, service, method);
Object result = invocation.process();
System.out.println("result: " + result);
/*
* 正常输出:
* >>> before1.before
* >>> before2.before
* Service.doService()
* >>> afterReturn2.afterReturn
* >>> after2.after
* >>> afterReturn1.afterReturn
* >>> after1.after
* result: ok
* */
/*
* 异常输出:
* >>> before1.before
* >>> before2.before
* Service.doService()
* >>> afterThrowing2.afterThrowing
* >>> after2.after
* >>> afterThrowing1.afterThrowing
* >>> after1.after
* */
}
}
JdkDynamicAopProxy
他是InvocationHandler的实现类,在invoke方法中实现了JDK代理的拦截逻辑。
invoke方法
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;
try {
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 1. 将Advisor集转换成MethodInterceptor链
// 和Cglib代理一样
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fallback on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
} else {
// We need to create a method invocation...
// 2. 构建一个ReflectiveMethodInvocation并执行拦截器链
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 执行调用链
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("");
}
return retVal;
} finally {
// 略
}
}
整体上和Cglib代理的拦截器逻辑一样。
后续ReflectiveMethodInvocation的proceed()方法也也是一样的。