`
flychao88
  • 浏览: 743546 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring AOP 源码实现过程

 
阅读更多

        我们看看在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) {   
            targettargetClass = 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以及反射机制对用户定义的拦截器链进行处理。

 

分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

Global site tag (gtag.js) - Google Analytics