代理对象创建好后,其实最终的拦截工作都是交给了MethodInvocation来做的,MethodInvocation有2个重要实现类ReflectiveMethodInvocation、CglibMethodInvocation
1、JDK代理对象的拦截器链创建交给:ReflectiveMethodInvocation
2、Cglib代理对象的拦截器链创建交给:CglibMethodInvocation,其中CglibMethodInvocation继承了ReflectiveMethodInvocation
注意拦截器链的创建是在代理对象被执行的时候绑定,不是代理对象创建时绑定的。
当我们代理对象生成后执行目标方法,先被JDK代理的invoke方法拦截,或者被Cglib的intercept方法拦截。在invoke和intercept方法内部会生成拦截器链,然后一层层调用拦截器,并且这种调用不是通过for循环的方式,而是通过职责链的模式调用。
下面是invoke方法和intercept方法创建拦截器链的代码
//JDK生成拦截器链,chain参数是拦截器集合
MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
//Cglib生成拦截器链,chain参数是拦截器集合
CglibMethodInvocation invocation = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy);
//执行拦截器链
retVal = invocation.proceed();//职责链模式
其中拦截器集合chain的获取是通过ProxyCreatorSupport.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)来得到的
getInterceptorsAndDynamicInterceptionAdvice里面就是根据切面的类型,分为"切点切面"和"引介切面",如果是"切点切面"就通过方法层面匹配符合切点表达式的通知,如果是引介切面,就通过类的层面找到符合类型规则的通知。关于这两种类型的切面可以参考我的这篇文章切点切面和引介切面
这里关于MethodInvocation接口以及的父类子类,并关于getInterceptorsAndDynamicInterceptionAdvice方法是如何获取拦截器集合做简单介绍
public interface Joinpoint {
//执行拦截器链
Object proceed() throws Throwable;
......
}
public interface Invocation extends Joinpoint {
//获取参数,例如方法的参数
Object[] getArguments();
}
public interface MethodInvocation extends Invocation {
//返回正在被调用的方法,也就是Method
Method getMethod();
}
ReflectiveMethodInvocation是Jdk使用的,CglibMethodInvocation是Cglib使用的,并CglibMethodInvocation还继承了ReflectiveMethodInvocation
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
protected final Object proxy; // 代理对象
protected final Object target; // 目标对象,持有目标对象是为了通过Method调用目标对象方法。
protected final Method method; // 被拦截的方法
......
protected final List<?> interceptorsAndDynamicMethodMatchers;//拦截器集合
private int currentInterceptorIndex = -1;//当前拦截器所在集合中的下标
//1、Spring内部使用的类
protected ReflectiveMethodInvocation(Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments,
@Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
// 找到桥接方法,作为最后执行的方法。
this.method = BridgeMethodResolver.findBridgedMethod(method);
// 对参数进行适配
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
。。。。。。
//2、这里是递归调用的方式,执行所有的拦截器
@Override
public Object proceed() throws Throwable {
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
//调用了目标方法,执行到这说明拦截器链到了链尾
return invokeJoinpoint();
}
//获取集合中的MethodInterceptor,注意这里++在前
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//InterceptorAndDynamicMethodMatcher它是Spring内部使用的一个类。很简单,就是把MethodInterceptor实例和MethodMatcher放在了一起。看看在advisor chain里面是否能够匹配上
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 匹配拦截器是否适用于这个目标方法
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
} else {
//不匹配跳过此拦截器,执行下一个拦截器,递归调用。
return proceed();
}
} else {
// 直接执行此拦截器。说明之前已经匹配好了,只有匹配上的方法才会被拦截进来的
// 这里传入this就是传入了ReflectiveMethodInvocation,从而形成了一个链条了
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
//执行Method方法
protected Object invokeJoinpoint() throws Throwable {
//通过目标对象target,执行目标对象的method的方法
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
}
CglibMethodInvocation因为继承了ReflectiveMethodInvocation,所以拥有父类所具备的能力,只是多了一个methodProxy属性
private static class CglibMethodInvocation extends ReflectiveMethodInvocation {
@Nullable
private final MethodProxy methodProxy;//代理方法,这个是什么
public CglibMethodInvocation(Object proxy, Object target, Method method,
Object[] arguments, Class<?> targetClass,
List<Object> interceptorsAndDynamicMethodMatchers, MethodProxy methodProxy) {
super(proxy, target, method, arguments, targetClass, interceptorsAndDynamicMethodMatchers);
//做出了特殊处理,methodProxy是特有的参数,表示被CGLIB拦截的时候的类
//MethodProxy:为生成代理类对方法的代理引用,使用MethodProxy比直接调用JDK本身的Method直接执行方法效率会有提升。
//MethodProxy有两个重要的方法:invoke和invokeSuper。
//method.getDeclaringClass用来判断当前这个方法是哪个类的方法。
//若该方法是public方法 且method不是Object类的方法,且method不是equals,且method不是hashCode,且 method不是toString方法,返回methodProxy对象。
this.methodProxy = (Modifier.isPublic(method.getModifiers())
&& method.getDeclaringClass() != Object.class
&& !AopUtils.isEqualsMethod(method)
&& !AopUtils.isHashCodeMethod(method)
&& !AopUtils.isToStringMethod(method) ?
methodProxy : null);
}
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
//如果符合上述条件,调用methodProxy去执行目标方法。(使用FastClass调用)
return this.methodProxy.invoke(this.target, this.arguments);
}
else {
return super.invokeJoinpoint();
}
}
}
获取符合规则的拦截器
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;
}
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Advised config, Method method, @Nullable Class<?> targetClass) {
//通过单例方式创建DefaultAdvisorAdapterRegistry实例,DefaultAdvisorAdapterRegistry是advisor的适配器,主要用来处理advisor-切面
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//获取所有的Advisor-切面,切面 = 切点 + 通知,这里的通知,我们就可以把他看做拦截器
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) {
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) {//如果是AspectJ都是走这种匹配
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
} else {
match = mm.matches(method, actualClass);
}
//如果切点的MethodMatcher都匹配这个method,拿到切面里面的"通知"
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
。。。。
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;
}
本文引至:https://www.cnblogs.com/chenxingyang/p/15559346.html