前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为我们提供AOP功能的;
在JdkDynamicAopProxy中生成Proxy对象的时候:
-
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
这里的this参数对应的是InvocationHandler对象,这里我们的JdkDynamicAopProxy实现了这个接口,也就是说当Proxy对象的函数被调用的时候,这个InvocationHandler的invoke方法会被作为回调函数调用,下面我们看看这个方法的实现:
-
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-
MethodInvocation invocation = null;
-
Object oldProxy = null;
-
boolean setProxyContext = false;
-
-
TargetSource targetSource = this.advised.targetSource;
-
Class targetClass = null;
-
Object target = null;
-
-
try {
-
// Try special rules for equals() method and implementation of the
-
// Advised AOP configuration interface.
-
-
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
-
// What if equals throws exception!?
-
// This class implements the equals(Object) method itself.
-
return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;
-
}
-
if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
-
// This class implements the hashCode() method itself.
-
return new Integer(hashCode());
-
}
-
if (Advised.class == method.getDeclaringClass()) {
-
// service invocations on ProxyConfig with the proxy config
-
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
-
}
-
-
Object retVal = null;
-
-
if (this.advised.exposeProxy) {
-
// make invocation available if necessary
-
oldProxy = AopContext.setCurrentProxy(proxy);
-
setProxyContext = true;
-
}
-
-
// May be <code>null</code>. Get as late as possible to minimize the time we "own" the target,
-
// in case it comes from a pool.
-
// 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例池或者是一个简单的JAVA对象
-
target = targetSource.getTarget();
-
if (target != null) {
-
targetClass = target.getClass();
-
}
-
-
// get the interception chain for this method
-
// 这里获得定义好的拦截器链
-
List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
-
this.advised, proxy, 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
-
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
-
}
-
else {
-
// We need to create a method invocation...
-
// invocation = advised.getMethodInvocationFactory().getMethodInvocation(
-
// proxy, method, targetClass, target, args, chain, advised);
-
// 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的相应方法
-
// 这里通过构造一个ReflectiveMethodInvocation来实现,下面我们会看这个ReflectiveMethodInvocation类
-
invocation = new ReflectiveMethodInvocation(
-
proxy, target, method, args, targetClass, chain);
-
-
// proceed to the joinpoint through the interceptor chain
-
// 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的目标方法
-
retVal = invocation.proceed();
-
}
-
-
// massage return value if necessary
-
if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) {
-
// 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;
-
}
-
return retVal;
-
}
-
finally {
-
if (target != null && !targetSource.isStatic()) {
-
// must have come from TargetSource
-
targetSource.releaseTarget(target);
-
}
-
-
if (setProxyContext) {
-
// restore old proxy
-
AopContext.setCurrentProxy(oldProxy);
-
}
-
}
-
}
我们先看看目标对象方法的调用,这里是通过AopUtils的方法调用 - 使用反射机制来对目标对象的方法进行调用:
-
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
-
throws Throwable {
-
-
// Use reflection to invoke the method.
-
// 利用放射机制得到相应的方法,并且调用invoke
-
try {
-
if (!Modifier.isPublic(method.getModifiers()) ||
-
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
-
method.setAccessible(true);
-
}
-
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("Couldn't access method: " + method, ex);
-
}
-
}
对拦截器链的调用处理是在ReflectiveMethodInvocation里实现的:
-
public Object proceed() throws Throwable {
-
// We start with an index of -1 and increment early.
-
// 这里直接调用目标对象的方法,没有拦截器的调用或者拦截器已经调用完了,这个currentInterceptorIndex的初始值是0
-
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) {
-
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.
-
// 这里获得相应的拦截器,如果拦截器可以匹配的上的话,那就调用拦截器的invoke方法
-
InterceptorAndDynamicMethodMatcher dm =
-
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
-
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
-
return dm.interceptor.invoke(nextInvocation());
-
}
-
else {
-
// Dynamic matching failed.
-
// Skip this interceptor and invoke the next in the chain.
-
// 如果拦截器匹配不上,那就调用下一个拦截器,这个时候拦截器链的位置指示后移并迭代调用当前的proceed方法
-
this.currentInterceptorIndex++;
-
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(nextInvocation());
-
}
-
}
这里把当前的拦截器链以及在拦截器链的位置标志都clone到一个MethodInvocation对象了,作用是当前的拦截器执行完之后,会继续沿着得到这个拦截器链执行下面的拦截行为,也就是会迭代的调用上面这个proceed:
-
private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {
-
ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();
-
invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1;
-
invocation.parent = this;
-
return invocation;
-
}
这里的nextInvocation就已经包含了当前的拦截链的基本信息,我们看到在Interceptor中的实现比如TransactionInterceptor的实现中:
-
public Object invoke(final MethodInvocation invocation) throws Throwable {
-
......//这里是TransactionInterceptor插入的事务处理代码,我们会在后面分析事务处理实现的时候进行分析
-
try {
-
//这里是对配置的拦截器链进行迭代处理的调用
-
retVal = invocation.proceed();
-
}
-
......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理
-
else {
-
try {
-
Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,
-
new TransactionCallback() {
-
public Object doInTransaction(TransactionStatus status) {
-
//这里是TransactionInterceptor插入对事务处理的代码
-
TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);
-
//这里是对配置的拦截器链进行迭代处理的调用,接着顺着拦截器进行处理
-
try {
-
return invocation.proceed();
-
}
-
......//省略了和事务处理的异常处理代码 ,也是TransactionInterceptor插入的处理
-
}
从上面的分析我们看到了Spring AOP的基本实现,比如Spring怎样得到Proxy,怎样利用JAVA Proxy以及反射机制对用户定义的拦截器链进行处理。