Spring AOP深入理解之拦截器调用

Posted brucemengbm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring AOP深入理解之拦截器调用相关的知识,希望对你有一定的参考价值。

Spring AOP深入理解之拦截器调用

Spring AOP代理对象生成回想

上一篇博客中:深入理解Spring AOP之二代理对象生成介绍了Spring代理对象是怎样生成的,当中重点介绍了JDK动态代理方式,简单回想下代理对象生成过程:

1、上面讲到了两种生成代理对象的方法,一种是通过ProxyFactory,一种是通过ProxyFactoryBean。

第一种获取比較简单,可是须要手工的进行写代码。而另外一种是通过Spring的IOC机制来控制Bean的生成。

2、不管是ProxyFactory或者ProxyFactoryBean都是要通过createAopProxy().getProxy()来获取对应的代理对象,而通过Proxyfactory比較直接,上面重点介绍的是通过ProxyFactoryBean获得proxy。
3、首先,找到ProxyFactoryBean的getObject方法,为什么?(主要是跟Bean容器中getObject能返回代理对象)
4、其次调用getSingletonInstance(),在getSingletonInstance方法中引入了super中的方法,super是指ProxyCreatorSupport。这里ProxyCreatorSupport是ProxyFactoryBean和ProxyFactory的父类。已经做了非常多工作,仅仅需在ProxyFactoryBean的getObject()方法中通过父类的createAopProxy()取得对应的AopProxy。
5、跟踪createAopProxy方法,追踪到了ProxyCreatorSupport中,然后,借助了AopProxyFactory。此时得到的aopProxyFactory。在构造函数中已经定义为DefaultAopProxyFactory
6、进入DefaultAopProxyFactory中,找到createAopProxy方法,在这里推断是调用JDK动态或者CGlib动态中的一种。

既然代理对象已经生成,那么拦截器是怎样被调用的呢

回想下JdkDynamicAopProxy中生成proxy方法

@Override
    public Object getProxy(ClassLoader classLoader) {
        if (logger.isDebugEnabled()) {
            logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
        }
        Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
        findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
        return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }

看最后一句return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)。这个地方的三个參数在博客动态代理中做过具体介绍。再回想下

  • classloader类载入器,定义了由哪个ClassLoader对象来对生成的代理对象进行载入

  • proxiedInterfaces,一个Interface对象的数组,表示的是我将要给我须要代理的对象提供一组什么接口

  • this,表示JdkDynamicAopProxy自身,由于JdkDynamicAopProxy实现了InvocationHandler接口

动态代理这篇博客中我们分析过。生成的proxy代理类被调用时。会调用super.h.method()方法,这里的super一般指的是Proxy。而Proxy中有一个InvocationHandler,即h。所以InvocationHandler的invoke方法会被作为回调函数调用

@Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        MethodInvocation invocation;
        Object oldProxy = null;
        boolean setProxyContext = false;

        TargetSource targetSource = this.advised.targetSource;
        Class<?> targetClass = null;
        Object target = null;

        try {
            if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
                //目标对象未实现equals方法
                return equals(args[0]);
            }
            if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
                //目标对象未实现hashcode方法
                return hashCode();
            }
            if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                    method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            //这里就是目标对象方法的调用
                return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
            }

            Object retVal;

            if (this.advised.exposeProxy) {
                // 获得当前的对象
                oldProxy = AopContext.setCurrentProxy(proxy);
                setProxyContext = true;
            }

            //目标对象可能源自一个池或者一个简单的方法
            target = targetSource.getTarget();
            if (target != null) {
                targetClass = target.getClass();
            }

            // 得到拦截器链
            List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

            // 检查是否定义了拦截器方法,假设没有的话直接调用目标方法

            if (chain.isEmpty()) {

                retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);
            }
            else {
                //我们须要创建一个调用方法
                invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
                // proceed内部实现了递归调用遍历拦截器链
                retVal = invocation.proceed();
            }

            Class<?

> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { retVal = proxy; } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { throw new AopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // 释放target对象 targetSource.releaseTarget(target); } if (setProxyContext) { // 替换回原来的proxy AopContext.setCurrentProxy(oldProxy); } } }

上面的invoke()主要分为三部分

  • 拦截器链的获取, this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)

  • 目标对象方法的调用,即invokeJoinpointUsingReflection()方法
  • 拦截器对象方法的调用,即ReflectiveMethodInvocation中proceed()

    首先看拦截器链是如获得的。

    进入AdvisedSupport(advised为AdvisedSupport实例)的getInterceptorsAndDynamicInterceptionAdvice()方法

    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 的对应方法中获取,继续跟踪AdvisorChainFactory,发现定义为new DefaultAdvisorChainFactory(),这里是不是有一点眼熟,对的,在上一篇中讲到动态代理是也有一个DefaultAopProxy。进入DefaultAdvisorChainFactory中的对应方法。比較长

    /** 
        * 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.假设是IntroductionAdvisor, 
        * 则推断此Advisor是否能应用到目标类targetClass上.假设是PointcutAdvisor,则推断 
        * 此Advisor是否能应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回. 
        */  
    
        public List getInterceptorsAndDynamicInterceptionAdvice(Advised config, Methodmethod, Class targetClass) {
    
           List interceptorList = new ArrayList(config.getAdvisors().length);
    
           //查看是否包括IntroductionAdvisor
           boolean hasIntroductions = hasMatchingIntroductions(config,targetClass);
    
           //这里实际上注冊一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor
           AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    
           Advisor[] advisors = config.getAdvisors();
            for (int i = 0; i <advisors.length; i++) {
               Advisor advisor = advisors[i];
               if (advisor instanceof PointcutAdvisor) {
                    // Add it conditionally.
                    PointcutAdvisor pointcutAdvisor= (PointcutAdvisor) advisor;
                    if(config.isPreFiltered() ||pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
                        //TODO: 这个地方这两个方法的位置能够互换下
                        //将Advisor转化成Interceptor
                        MethodInterceptor[]interceptors = registry.getInterceptors(advisor);
    
                        //检查当前advisor的pointcut能否够匹配当前方法
                        MethodMatcher mm =pointcutAdvisor.getPointcut().getMethodMatcher();
    
                        if (MethodMatchers.matches(mm,method, targetClass, hasIntroductions)) {
                            if(mm.isRuntime()) {
                                // Creating a newobject instance in the getInterceptors() method
                                // isn‘t a problemas we normally cache created chains.
                                for (intj = 0; j < interceptors.length; j++) {
                                   interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j],mm));
                                }
                            } else {
                                interceptorList.addAll(Arrays.asList(interceptors));
                            }
                        }
                    }
               } else if (advisor instanceof IntroductionAdvisor){
                    IntroductionAdvisor ia =(IntroductionAdvisor) advisor;
                    if(config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
                        Interceptor[] interceptors= registry.getInterceptors(advisor);
                        interceptorList.addAll(Arrays.asList(interceptors));
                    }
               } else {
                    Interceptor[] interceptors =registry.getInterceptors(advisor);
                    interceptorList.addAll(Arrays.asList(interceptors));
               }
           }
           return interceptorList;
    }
    
    

    注意上面代码中的一行,注冊一系列AdvisorAdapter。找到GlobalAdvisorAdapterRegistry,事实上定义为 new DefaultAdvisorAdapterRegistry(),又是default~~~

    AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
    
    instance = new DefaultAdvisorAdapterRegistry();
    
    public DefaultAdvisorAdapterRegistry() {
            registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
            registerAdvisorAdapter(new AfterReturningAdviceAdapter());
            registerAdvisorAdapter(new ThrowsAdviceAdapter());
        }
    

    所以registry事实上为调用了DefaultAdvisorAdapterRegistry的构造函数,然后才干在将Advisor转化成Interceptor时。调用DefaultAdvisorAdapterRegistry的getInterceptors()方法。

        @Override
        public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
            List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(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[interceptors.size()]);
        }
    
    

    这里的MethodInterceptor[]返回值,正好能够匹配上面代码中的 MethodInterceptor[]interceptors = registry.getInterceptors(advisor);

    目标对象方法的调用

    来看看invokeJoinpointUsingReflection()。即上面所说的目标对象方法的调用,事实上是通过AopUtils的方法调用。使用反射机制来对目标对象的方法进行的:

        public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)
                throws Throwable {
    
            // 通过反射机制来获得对应的方法。并调用invoke
            try {
                ReflectionUtils.makeAccessible(method);
                return method.invoke(target, args);
            }
            catch (InvocationTargetException ex) {
    
                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);
            }
        }
    

    拦截器方法运行

    看看拦截器对象,即ReflectiveMethodInvocation中proceed()方法的调用

    invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    
    retVal = invocation.proceed();
    
    

    invocation是一个new ReflectiveMethodInvocation()实例,找到ReflectiveMethodInvocation的proceed()方法

    
    private int currentInterceptorIndex = -1;
    
        @Override
        public Object proceed() throws Throwable {
            //  currentInterceptorIndex初始化的长度为-1,以下就就是推断          //interceptorsAndDynamicMethodMatchers长度是否为0
            if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                return invokeJoinpoint();
            }
    
            Object interceptorOrInterceptionAdvice =
                    this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
            if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
                //匹配是否为正确的方法逻辑,(MethodMatcher)能够看出为匹配假设不是就调用下一个
                InterceptorAndDynamicMethodMatcher dm =
                        (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
                if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
                    return dm.interceptor.invoke(this);
                }
                else {
                    //匹配失败,跳过这个拦截器,继续下一个
                    return proceed();
                }
            }
            else {
                // 假设是interceptor。则调用invoke方法。这是为了兼容
    
                return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
            }
        }
    


  • 以上是关于Spring AOP深入理解之拦截器调用的主要内容,如果未能解决你的问题,请参考以下文章

    对Spring AOP的进一步深入理解

    Spring系列之AOP分析之对目标对象的拦截过程

    Spring框架系列 - 深入浅出Spring核心之面向切面编程(AOP)

    这一次搞懂Spring代理创建及AOP链式调用过程

    深入理解Spring的IOC容器

    使用AOP拦截器获取一次请求流经方法的调用次数和调用耗时