<>增强器(上)

2019-05-27  本文已影响0人  monk87

背景

事情的起因是这样的 。中间件这边做了一套缓存sdk框架。其实是对spring mvc那一套做了一些功能封装并且增加了一些属性,支持了自定义过期时间,请求序列化等等操作。再给也无妨同学接入的时候,出现了尴尬的一幕 : 按照说明文档接入了以后(其实就是引入xml,和dependency)。在想要加缓存的地方加上我们自定义的注解。 结果是 : 不起作用。 并没有走缓存,还是去查数据库。因此我们对spring的增强器那块代码做了一个review。增强器整理分为上下2部分。上篇讲述获取增强器的具体流程。下面讲述获取增强器的机制。会在下篇讲述为什么增强器没有拦截成功。

Spring 增强器的获取

增强器获取是在spring容器启动的时候,会遍历每一个拦截的类,并对其的增强器进行加载 。

// org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
           //获取容器中所有的增强器 (其实包含集成Advisor接口的和带有@Aspect注解的两类对象都会得到。
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
          //查询可以应用到当前对象的增强器
        List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        extendAdvisors(eligibleAdvisors);
        if (!eligibleAdvisors.isEmpty()) {
            eligibleAdvisors = sortAdvisors(eligibleAdvisors);
        }
        return eligibleAdvisors;
    }

可以看到,这个是一个抽象类。执行这个代码的主体对象现在一般是这个类AnnotationAwareAspectJAutoProxyCreator,主要是因为注解已经非常普遍了。
这个类重写了查找所有增强器的方法 findCandidateAdvisors,如下

//AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
        @Override
    protected List<Advisor> findCandidateAdvisors() {
        // Add all the Spring advisors found according to superclass rules.
                //可以看到这里其实调用的是父类的查询所有实现了Advisor接口的
                //增强器
        List<Advisor> advisors = super.findCandidateAdvisors();
        // Build Advisors for all AspectJ aspects in the bean factory.
                //这里把对@Aspect的支持也增加进来
        advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
        return advisors;
    }

另外,可以看到第一步的父类中寻找增强器的代码 ,寻找advisor其实是通过类 BeanFactoryAdvisorRetrievalHelper来找的

//BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
public List<Advisor> findAdvisorBeans() {
        // Determine list of advisor bean names, if not cached already.
        String[] advisorNames = null;
        synchronized (this) {
            advisorNames = this.cachedAdvisorBeanNames;
            if (advisorNames == null) {
                // Do not initialize FactoryBeans here: We need to leave all regular beans
                // uninitialized to let the auto-proxy creator apply to them!
                advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
                        this.beanFactory, Advisor.class, true, false);
                this.cachedAdvisorBeanNames = advisorNames;
            }
        }
        if (advisorNames.length == 0) {
            return new LinkedList<Advisor>();
        }

        List<Advisor> advisors = new LinkedList<Advisor>();
        for (String name : advisorNames) {
            if (isEligibleBean(name)) {
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipping currently created advisor '" + name + "'");
                    }
                }
                else {
                    try {
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    }
                    catch (BeanCreationException ex) {
                        Throwable rootCause = ex.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {
                            BeanCreationException bce = (BeanCreationException) rootCause;
                            if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Skipping advisor '" + name +
                                            "' with dependency on currently created bean: " + ex.getMessage());
                                }
                                // Ignore: indicates a reference back to the bean we're trying to advise.
                                // We want to find advisors other than the currently created bean itself.
                                continue;
                            }
                        }
                        throw ex;
                    }
                }
            }
        }
        return advisors;
    }

到此,增强器的获取,可以看到一个大致的轮廓了 。更细节的可以后面慢慢赏析。

上一篇 下一篇

猜你喜欢

热点阅读