Spring源码解析(十二)-配置通知器和Advice的通知实现

1.配置通知器

其实如何配置拦截器的问题,可以转化为拦截器元素是从哪来的,又在哪边配置的问题。看过上章Aop拦截器调用解析的博文的朋友肯定有印象存在着一行代码

// 获得该方法定义好的连接器链.
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
 
 

这里的advised是AdvisedSupport对象,我们来看一下它的具体实现

   //这里运用缓存,存入了Map>
   //key:Method ; value: advisor chain List
   public List getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
        MethodCacheKey cacheKey = new MethodCacheKey(method);
        List cached = this.methodCache.get(cacheKey);
        if (cached == null) {
            cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
                    this, method, targetClass);
            this.methodCache.put(cacheKey, cached);
        }
        return cached;
    }
 
 
DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法
    //获取通知
    @Override
    public List getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class targetClass) {

        //根据AOP中配置创建通知器链的集合.
        List interceptorList = new ArrayList(config.getAdvisors().length);
        //获取目标类的class对象
        Class actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
        //判断Advisors是否符合配置要求
        boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
        //获取AdvisorAdapterRegistry对象
        AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
        //遍历advisors
        for (Advisor advisor : config.getAdvisors()) {
            //PointcutAdvisor
            if (advisor instanceof PointcutAdvisor) {
                PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
                //AOP配置对通知已经过滤或者当前切入点的类过滤器匹配目标类
                if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
                    //获取advisor中的方法拦截器列表
                    MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
                    //获取advisor切点的方法匹配器
                    MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
                    //目标类方法匹配切点
                    if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
                       //方法匹配器是运行时动态匹配的
                        if (mm.isRuntime()) {
                            //将方法拦截器和方法匹配器封装后添加到返回的通知器集合中.
                            for (MethodInterceptor interceptor : interceptors) {
                                interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
                            }
                        }
                        else {
                            //将方法拦截器添加到返回的通知器集合中
                            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;
    }

    private static boolean hasMatchingIntroductions(Advised config, Class actualClass) {
        for (int i = 0; i < config.getAdvisors().length; i++) {
            Advisor advisor = config.getAdvisors()[i];
            //通知器是引入通知器
            if (advisor instanceof IntroductionAdvisor) {
                IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
                //是否匹配目标类
                if (ia.getClassFilter().matches(actualClass)) {
                    return true;
                }
            }
        }
        return false;
    }
 
 

在ProxyFactoryBean的getObject方法中对advisor进行初始化时,从XML配置中获取了Advisor通知器。在初始化Advisor中,可以看到对IOC容器的一个getBean回调来得到配置好的Advisor通知器。那么ProxyFactoryBean是如何获得IOC容器,然后通过回调来获得Advisor的呢?对于IOC容器的使用,如果需要回调容器,前提是当前的Bean实现BeanFactoryAware接口,并实现setBeanFactory方法,同时设置一个属性来持有IOC容器,就可以在Bean中取得IOC容器并进行回调了,而ProxyFactoryBean就实现了这个接口。ProxyFactoryBean给出通知器的名字(这些名字在XML中interceptorNames的list中),在IOC对FactoryBean进行依赖注入的时候,会直接注入到FactoryBean的interceptorNames的属性中。完成这个过程以后,ProxyFactoryBean就获得了配置的通知器。

2.Advice的通知实现

首先我们来看下如何获取通知器的通知,我们在解析如何获取配置通知器的时候出现过如下这行代码

AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

因为AdvisorAdapterRegistry是一个接口,我们来看一下它的默认实现类DefaultAdvisorAdapterRegistry


 public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {
    //通知器适配器集合
    private final List adapters = new ArrayList(3);


    /**
     * 构造方法,只有3种通知器适配器.
     */
    public DefaultAdvisorAdapterRegistry() {
        registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
        registerAdvisorAdapter(new AfterReturningAdviceAdapter());
        registerAdvisorAdapter(new ThrowsAdviceAdapter());
    }

    //将通知封装为通知器
    @Override
    public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
        if (adviceObject instanceof Advisor) {
            return (Advisor) adviceObject;
        }
        if (!(adviceObject instanceof Advice)) {
            throw new UnknownAdviceTypeException(adviceObject);
        }
        Advice advice = (Advice) adviceObject;
        if (advice instanceof MethodInterceptor) {
            return new DefaultPointcutAdvisor(advice);
        }
        for (AdvisorAdapter adapter : this.adapters) {
            //检查符合的advice.
            if (adapter.supportsAdvice(advice)) {
                return new DefaultPointcutAdvisor(advice);
            }
        }
        throw new UnknownAdviceTypeException(advice);
    }

    //获得通知器的通知 
    @Override
    public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
        List interceptors = new ArrayList(3);
        //获取advice通知
        Advice advice = advisor.getAdvice();
        //如果通知是MethodInterceptor类型,则加入interceptors
        if (advice instanceof MethodInterceptor) {
            interceptors.add((MethodInterceptor) advice);
        }
        //对通知进行适配,从适配器(MethodBeforeAdviceAdapter,AfterReturningAdviceAdapter,ThrowsAdviceAdapter)中取出封装好AOP编织功能的拦截器
        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()]);
    }

    //注册通知适配器
    @Override
    public void registerAdvisorAdapter(AdvisorAdapter adapter) {
        this.adapters.add(adapter);
    }

}

我们以MethodBeforeAdviceAdapter为例,看一下MethodBeforeAdviceAdapter的具体实现

 class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

    @Override
    public boolean supportsAdvice(Advice advice) {
        return (advice instanceof MethodBeforeAdvice);
    }

    @Override
    public MethodInterceptor getInterceptor(Advisor advisor) {
        MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
        return new MethodBeforeAdviceInterceptor(advice);
    }

}
 public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

    private MethodBeforeAdvice advice;


    /**
     * Create a new MethodBeforeAdviceInterceptor for the given advice.
     * @param advice the MethodBeforeAdvice to wrap
     */
    public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
        Assert.notNull(advice, "Advice must not be null");
        this.advice = advice;
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
        return mi.proceed();
    }

}

如代码所示,MethodBeforeAdviceInterceptor 完成的是对MethodBeforeAdvice 通知的封装,可以在MethodBeforeAdviceInterceptor 设计的invoke回调方法中,看到首先触发了advice的before方法,然后才是MethodInvocation的proceed方法调用。而proceed方法已经在第十一章中分析完毕。以上则是Spring AOP的所有内容。

你可能感兴趣的:(Spring源码解析(十二)-配置通知器和Advice的通知实现)