在上一篇章的学习中了解到AOP代理对象的执行过程,AOP中的代理对象有JDK代理与CGLIB代理两种方式,这两种代理对象在对目标对象的方法进行拦截,分别通过JdkDynamicAopProxy的invoke和DynamicAdvisedInterceptor的intercept来拦截。
这两种的原理是一致的:
1、先判断有没有拦截器链,如果没有,那么直接执行目标对象的方法
2、如果有拦截器链,则封装成ReflectiveMethodInvocation,执行proceed方法依次调用拦截器,然后返回目标方法执行的结果。
今天就来看看AOP的拦截器链是如何实现的。
拦截器链如何拦截
关于AOP拦截器链的实现,当然是通过ReflectiveMethodInvocation的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);
}
}
拦截器链的调用是这样的:
依次匹配各个拦截器,如果匹配成功,则执行这个拦截器,否则继续往后面匹配,直到所有拦截器都执行完毕,则调用目标对象的方法。
看到这个,刚开始有点疑惑。
1、拦截器执行完毕才调用目标对象?这只是前置增强,那么后置增强呢,异常增强呢??
2、这里看到匹配了拦截器以后,直接return 拦截器执行的结果,难道只能匹配一个拦截器??而且神奇的是,这样匹配后直接return了,那目标方法岂不是没有调用??
OK,这一切的疑惑,都要从拦截器的invoke去理解,解答~~
因此这里需要搞清楚interceptorsAndDynamicMethodMatchers,也就是这一系列拦截器是从哪里引入进来的。
interceptorsAndDynamicMethodMatchers
这一系列拦截器,由ReflectiveMethodInvocation的构造器传入,回到上一篇学习的代理对象的执行过程,我们可以追溯到拦截器链的获取代码:
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
而这里的advised,是AdvisedSupport,我们继续点进去看
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//拦截器链从advisorChainFactory去取。
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
这里可以看到拦截器链,是从advisorChainFactory中获取的,同时AdvisedSupport还对拦截器链做了缓存。
再看this.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.
//这里得到的是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;
//遍历通知
for (Advisor advisor : advisors) {
//如果是一个PointcutAdvisor,那么通知与切点都有了,这里需要去判断方法是否匹配这个pointCut,匹配就把这个加进拦截器链
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) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
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));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
getInterceptorsAndDynamicInterceptionAdvice中如果实现拦截器链的获取呢,主要关注registry.getInterceptors(advisor);
这个registry是一个DefaultAdvisorAdapterRegistry对象,并且在对象创建的时候,就注册了三个代理对象,
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
getInterceptors
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]);
}
这里以MethodBeforeAdviceAdapter为例来看一下如何获取拦截器
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();
//这是最终获取到的拦截器对象,也就是最终调用的invoke就是MethodBeforeAdviceInterceptor的invoke
return new MethodBeforeAdviceInterceptor(advice);
}
}
下面来看下,剥丝抽茧后最终得到的MethodBeforeAdviceInterceptor
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
//先调用before实现前置增强
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
//再去调用proceed进行下一个拦截器的执行
return mi.proceed();
}
}
至于后置与异常增强的适配器与相应的拦截器都是一样的原理,
在适配器里判断是否是对应的增强类型,在通过getInterceptor方法获取到对应的拦截器。
后置增强:
public Object invoke(MethodInvocation mi) throws Throwable {
Object retVal = mi.proceed();
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
return retVal;
}
异常增强:
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
catch (Throwable ex) {
Method handlerMethod = getExceptionHandler(ex);
if (handlerMethod != null) {
invokeHandlerMethod(mi, ex, handlerMethod);
}
throw ex;
}
}