上次我说到关于ProxyFactoryBean对象的getObject方法返回了一个代理对象。剩下的AOP实现过程就和jdk的代理模式相同。通过调用这个代理对象的方法(这个方法和目标对象是相同的),但是实际上是调用了invoke方法,通过反射来实现方法的增强。
关于jdk如何实现代理模式的反编译,底层的代码实现过程可以在这个博客中查看
https://blog.csdn.net/u013815218/article/details/52562536(转载)
目录
现在我们来看上次说的JdkDynamicAopProxy的getProxy方法的返回值
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
其中这个this指的是InvocationHandler对象,通过对这个接口的invoke方法的重写,实现了对目标对象的增强。也就是说我们Proxy对象的代理方法被调用时,JdkDynamicAopProxy的invoke方法作为Proxy对象的回调函数而被触发。那么实际上真正的增强工作都是在JdkDynamicAopProxy中的invoke方法实现了。
JDKDynamicAopProxy的invoke拦截
源代码有100多行,所以我就没有粘贴,可以到
org.springframework.aop.framework.JdkDynamicAopProxy中进行查看。
首先我们要获得目标对象
target = targetSource.getTarget();
之后我们要获得之前我们初始化的拦截器链。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
如果没有拦截器链(注意这个地方的拦截器实际上是对方法的增强操作),就直接执行相应的方法。
如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的方法。
通过构造一个ReflectiveMethodInvocation来实现。
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
在拦截器链上执行相应的加强方法。
retVal = invocation.proceed();
这个invocation将我们的拦截器链(也就是一系列的通知器)进行了封装,里面定义了各个加强方法。
书上还有关于目标对象方法的调用
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
method + "] on target [" + target + "]", ex);
}
catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}
实际上我们可以看到还是调用这个jdk自身的反射机制
return method.invoke(target, args);
AOP拦截器链的调用
关于AOP链的调用,就是AOP实现的核心部分了
我们需要分析一下这个proceed()方法。
首先我们沿着定义好的拦截器链进行处理
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
这个是为了递归查找我们合适的拦截器而设定的。
接下来需要对拦截器进行动态匹配,也就是我们之前说的pointcut,匹配正确的切点进行正确的方法加强。
如果不匹配,那么这个proceed方法就会被递归调用。
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
配置通知器
首先我们想要知道,在这个proceed()方法中的
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
这个拦截器链是怎么获取的呢。我们来看一下这个类的构造方法
protected ReflectiveMethodInvocation(
Object proxy, Object target, Method method, Object[] arguments,
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;
}
这个参数的配置是我们传入的一个入参。那么回到整个拦截器链的配置过程,
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
一切就都明白了,我们把之前我们获取到chain当做一个参数传给了我们的invocation对象。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
书上还为我们解释了拦截器如何从AdvisedSupport获得
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, 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 (DefaultAdvisorChainFactory对象)完成的
org.springframework.aop.framework.DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass)
在这个方法中,我们可以根据书中的代码进行分析。
首先我们的config持有了advisor链。至于为什么持有了advisor链呢,我们需要对原先的代码进行一下追踪。这个查找过程需要去看。
在我们之前创建代理对象的时候,我有提到过这个方法。
org.springframework.aop.framework.ProxyCreatorSupport
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
这个类继承了AdvisedSupport类,这就和之前的getInterceptorsAndDynamicInterceptionAdvice对应上了。
继续向上查找ProxyFactoryBean,在这个类中我们可以看到,它继承了ProxyCreatorSupport。而我们在配置它的时候为它声明了相应的advisors,这就是为什么说config已经为我们配置好了相应的advisor链。实际上这一系列的this对象归根到底都是内个最开始的ProxyFactoryBean对象。
具体的拦截器链的加入是通过AdvisorAdapterRegistry这个类来完成的。具体的代码我留作下一篇博客解释。