Spring事务管理(3)-AOP创建Advisors

在上一篇文章中,详细讲述了Spring中注册AOP解析器的过程。在这篇文章中,将进一步讲解Advisors的创建过程。
Spring中注册AOP解析器的所有操作都是针对AnnotationAwareAspectJAutoProxyCreator进行的。AnnotationAwareAspectJAutoProxyCreator是实现AOP的根本。首先观察AnnotationAwareAspectJAutoProxyCreator的类层次结构。
这里写图片描述
图1 AnnotationAwareAspectJAutoProxyCreator的类层次结构
从上图中可以看到,AnnotationAwareAspectJAutoProxyCreator继承AspectJAwareAdvisorAutoProxyCreator类,实现BeanPostProcessor接口。其中AspectJAwareAdvisorAutoProxyCreator是完成xml配置的代理创建。 我们知道,当一个类实现了BeanPostProcessor接口,那么在Spring在生成bean时会在实例化完成前调用postProcessAfterInitialization方法。
通过查看AnnotationAwareAspectJAutoProxyCreator的父类,在AbstractAutoProxyCreator中找到了postProcessAfterInitialization方法。

/**
* Create a proxy with the configured interceptors if the bean is
 * identified as one to proxy by the subclass.
 * @see #getAdvicesAndAdvisorsForBean
 */
public Object postProcessAfterInitialization(Object bean, String beanName) 
throws BeansException {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.containsKey(cacheKey)) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

在上述方法中,wrapIfNecessary对所有bean实例进行增强处理。其中最重要的逻辑是获得Advisors以及创建代理对象。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    // 如果bean已经处理,则从缓存中返回已经处理的bean
    if (beanName != null && this.targetSourcedBeans.containsKey(beanName)) {
        return bean;
    }
    // 如果bean被定义为不增强,则返回
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    // 如果是基础设置类,则不进行代理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }
    // 获得bean的增强方法
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        // 增强并返回代理对象
        Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

进一步跟进getAdvicesAndAdvisorsForBean函数。

protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
    // 寻找合适的增强方法
    List advisors = findEligibleAdvisors(beanClass, beanName);
    if (advisors.isEmpty()) {
        return DO_NOT_PROXY;
    }
    return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {
    // 寻找所有的增强方法
    List<Advisor> candidateAdvisors = findCandidateAdvisors();
    // 进一步寻找合适的增强方法
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    // 扩展增强方法
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        // 对增强方法进行排序
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}
  1. 寻找所有的增强方法candidateAdvisors
    findCandidateAdvisors方法包含多个实现方式,AnnotationAwareAspectJAutoProxyCreator的实现中包括寻找xml中配置的增强以及解析所有注解方法的增强。
protected List<Advisor> findCandidateAdvisors() {
    // Add all the Spring advisors found according to superclass rules.
    // 调用AbstractAdvisorAutoProxyCreator的findCandidateAdvisors
    // findCandidateAdvisors方法会寻找xml中配置的增强方法。
    List<Advisor> advisors = super.findCandidateAdvisors();
    // Build Advisors for all AspectJ aspects in the bean factory.
    // 添加所有注解方式的增强
    advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    return advisors;
}

1.1 寻找xml中配置的增强
此处寻找比较简单,由于xml在配置文件解析阶段以及生成bean,因此只要去beanFactory中获得所有的Advisor的的bean即可。

protected List<Advisor> findCandidateAdvisors() {
    // advisorRetrievalHelpers是BeanFactoryAdvisorRetrievalHelper的对象
    // 用来检索所有增强方法
return this.advisorRetrievalHelper.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!
        // 此处查找所有的名称,但不进行初始化
        // 如果此处进行初始化,遇到需要增强的bean时,会进入死循环
        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 {
                    // 从beanFactory中获得增强advisor,并添加到返回结果中
                advisors.add(this.beanFactory.getBean(name, Advisor.class));
                }
                catch (BeanCreationException ex) {
                    …
                    throw ex;
                }
            }
        }
    }
    return advisors;
}

1.2 查找带Aspect注解的增强
回到findCandidateAdvisors方法中,语句this.aspectJAdvisorsBuilder.buildAspectJAdvisors()寻找注解形式的增强器。

public List<Advisor> buildAspectJAdvisors() {
    List<String> aspectNames = null;

    synchronized (this) {
        aspectNames = this.aspectBeanNames;
        if (aspectNames == null) {
            List<Advisor> advisors = new LinkedList<Advisor>();
            aspectNames = new LinkedList<String>();
            // 从beanFactory中查找所有bean,包括父类中的bean
            // 递归查找
String[] beanNames = 
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
            for (String beanName : beanNames) {
                if (!isEligibleBean(beanName)) {
                    continue;
                }

                Class beanType = this.beanFactory.getType(beanName);
                if (beanType == null) {
                    continue;
                }

                // 判断是否包含Aspect注解
                if (this.advisorFactory.isAspect(beanType)) {
                    aspectNames.add(beanName);
                    // 创建AspectMetadata对象
                    // 在该对象中将通过beanTypep判断AspectJ的实例化模型
                    //
                    AspectMetadata amd = new AspectMetadata(beanType, beanName);
                    // 如果是Singleton实例化模型
                    // singleton实例化模型表示切面只会有一个实例
                    if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
                        //创建MetadataAwareAspectInstanceFactory
                        MetadataAwareAspectInstanceFactory factory =
                                    new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
                        // 获得所有增强
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
                            if (this.beanFactory.isSingleton(beanName)) {
                                this.advisorsCache.put(beanName, classAdvisors);
                            }
                            else {
                                this.aspectFactoryCache.put(beanName, factory);
                            }
                            advisors.addAll(classAdvisors);
                        }
                        else {
                            // Per target or per this.
                            if (this.beanFactory.isSingleton(beanName)) {
                                throw new IllegalArgumentException("Bean with name '" + beanName +
                                        "' is a singleton, but aspect instantiation model is not singleton");
                            }
                            MetadataAwareAspectInstanceFactory factory =
                                    new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
                            this.aspectFactoryCache.put(beanName, factory);
                            advisors.addAll(this.advisorFactory.getAdvisors(factory));
                        }
                    }
                }
                this.aspectBeanNames = aspectNames;
                return advisors;
            }
        }

        if (aspectNames.isEmpty()) {
            return Collections.EMPTY_LIST;
        }
        List<Advisor> advisors = new LinkedList<Advisor>();
        for (String aspectName : aspectNames) {
            List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
            if (cachedAdvisors != null) {
                advisors.addAll(cachedAdvisors);
            }
            else {
                MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
                advisors.addAll(this.advisorFactory.getAdvisors(factory));
            }
        }
        return advisors;
    }

以上代码看上去比较长,但其实流程相对清晰。首先查找Spring中所有的beanName,然后判断下该 bean是否带Aspect注解,如果存在注解,则获得该bean中的所有增强。
值得注意的是,在生成AspectMetadata时,会获得Aspect注解类的实例化模型。所谓实例化模型是指何时实例化切面。Spring AOP支持AspectJ的singleton、perthis、pertarget、pertypewithin实例化模型(目前不支持percflow、percflowbelow)。
singleton:切面只会有一个实例
perthis: 每个切入点表达式匹配的连接点对应的AOP对象都会创建一个新切面实例
pertarget: 每个切入点表达式匹配的连接点对象的目标对象都会创建一个新的切面实例
perwithin:

回到以上方法的this.advisorFactory.getAdvisors(factory),该语句返回所有的增强器。

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
    final Class<?> aspectClass = 
                maaif.getAspectMetadata().getAspectClass();
    final String aspectName = maaif.getAspectMetadata().getAspectName();
    validate(aspectClass);

    // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
    // so that it will only instantiate once.
    final MetadataAwareAspectInstanceFactory 
lazySingletonAspectInstanceFactory =
                new LazySingletonAspectInstanceFactoryDecorator(maaif);

    final List<Advisor> advisors = new LinkedList<Advisor>();
    // 查找切面类中的所有方法
    for (Method method : getAdvisorMethods(aspectClass)) {
        // 生成Advisor对象
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    // If it's a per target aspect, emit the dummy instantiating aspect.
    if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
        Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
        advisors.add(0, instantiationAdvisor);
    }

    // Find introduction fields.
    for (Field field : aspectClass.getDeclaredFields()) {
        Advisor advisor = getDeclareParentsAdvisor(field);
        if (advisor != null) {
            advisors.add(advisor);
        }
    }

    return advisors;
}

在生成所有Advisor的方法中,重点是寻找所有增强方法,并返回增强实例。其中getAdvisorMethods将方法所有增强方法。在这个方法中,将寻找aspectClass中所有的方法,并添加到集合中返回。

private List<Method> getAdvisorMethods(Class<?> aspectClass) {
    final List<Method> methods = new LinkedList<Method>();
    ReflectionUtils.doWithMethods(aspectClass, new 
ReflectionUtils.MethodCallback() {
public void doWith(Method method) throws IllegalArgumentException {
                // Exclude pointcuts
                if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
                    methods.add(method);
                }
            }
        });
        Collections.sort(methods, METHOD_COMPARATOR);
        return methods;
}

在上面的函数中,我们获得了aspectClass中的所有方法,接下来将根据方法生成Advisor对象了。

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif,
            int declarationOrderInAspect, String aspectName) {

    validate(aif.getAspectMetadata().getAspectClass());

    AspectJExpressionPointcut ajexp =
getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
    if (ajexp == null) {
        return null;
    }
    return new InstantiationModelAwarePointcutAdvisorImpl(
            this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}

可以看到Advisor最终返回的是InstantiationModelAwarePointcutAdvisorImpl对象。该对象包含了切点信息以及实例化的avdice(如果是singleton切面类型)。此处省略部分逻辑代码,在获得advice的函数中,包含如下逻辑。可以看到,不同的注解对象将返回不同的切面类型。

AbstractAspectJAdvice springAdvice;
    switch (aspectJAnnotation.getAnnotationType()) {
        case AtBefore:
            springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
                break;
            case AtAfter:
                springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
                break;
            case AtAfterReturning:
                springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
                AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterReturningAnnotation.returning())) {
                    springAdvice.setReturningName(afterReturningAnnotation.returning());
                }
                break;
            case AtAfterThrowing:
                springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
                AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
                if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
                    springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
                }
                break;
            case AtAround:
                springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
                break;
            case AtPointcut:
                if (logger.isDebugEnabled()) {
                    logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
                }
                return null;
            default:
                throw new UnsupportedOperationException(
                        "Unsupported advice type on method " + candidateAdviceMethod);
        }

归纳下寻找注解中的增强器的过程,首先查找Spring管理的所有bean,然后判断bean是否带有Aspect注解,如果存在,则进一步查找该bean中的所有增强方法,根据配置的@Before等注解生成不同的advisors。

  1. 寻找合适的增强方法findAdvisorsThatCanApply
    该过程相对简单,寻找class合适的增强。即通过pointcut注解进行判断即可。

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。
 总体来说 设计模式 分为三大类:创建型模式、结构型模式和行为型模式。 博主的上一篇文章已经提到过创建型模式,此外该文章还有设计模式概况和设计模式的六大原则。设计模式的六大原则是设计模式的核心思想,详情请看博主的另外一篇文章:  Java经典设计模式之五大创建模式(附实例和详解) 。 接下来我们看看结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。其中适配器模式主要分为三类:类的适配器模式、对象的适配器模式、接口的适配器模式。其中的对象的适配器模式是各种结构
大话设计模式 1 面向对象的好处 可维护、可重复、可扩展 。 2 包含的角色 简单工厂模式包含三个角色: 工厂类Factory :工厂类是用来制造产品的。因此,在Factory中有一个用于制造产品的Create函数或者Generate函数之类的函数。这个函数能够根据“标识符”的不同生成不同的ConcreteProduct,当然这些ConcreteProduct都是继承自AbstractProduct的。 抽象产品类AbstractProduct :抽象产品是从其他具体产品抽象出来的。抽象产品类只有一个。
Linux常用命令 (1)ls 查看当前目录下所有目录和文件 ls -l会将目录和文件竖着排,并且可以提供文件数据 上图最左边以“d”开头的是目录,以“-”开头的是文件。后面是文件和目录的权限,后面是占了多少空间的大小,然后是创建人和所有人是谁,然后是实际当中所占空间,后面是创建的时间,最右边是目录或文件的名字。 ls -m会适合左右屏幕宽度将目录和文件列出 后面的不常用的不再介绍,用到可以去查 (2)cd 打开目录 cd /打开根目录 cd /dev 打开dev目录(绝对路径) cd /之后再cd dev

Web Service学习总结 - 2016-07-22 18:07:07

Web service到底是什么, 在什么情况下你应该使用Web service:      研究一下当前的应用开发程序 ,你会发现一个绝对的倾向:人们开始偏爱基于浏览器 的客户端应用程序。这当然不是因为客户端能够提供更好的用户界面,而是因为它能够避免花在桌面应用程序 发布上的高成本。发布桌面应用程序 成本很高,一半是因为应用程序安装和配置的问题,另一半是因为客户端和服务器之间通信的问题。      传统的Windows客户应用程序使用DCOM来与服务器进行通信和调用远程对象。配置好DCOM使其在一个大型
咱们不搞一开始就一大堆理论知识介绍,怕把人讲懵了...... 咱们换一个思维方式——"从现象看本质",先说说我们看到了什么,再从看到的现象中提出问题,最后深入寻找答案。 我们看到的 cookie 我自己创建了一个网站,网址为 http://ppsc.sankuai.com 。在这个网页中我设置了几个 cookie : JSSESSIONID , PA_VTIME , skmtutc , test 。 在 chrome 浏览器中打开这个网站,进入开发者模式,点击 Resources 栏 - 选择 cooki
MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。 文档顶层结构: configuration 配置           properties 属性           settings 设置           typeAliases 类型命名           typeHandlers 类型处理器           objectFactory 对象工厂           plugins 插件           envir
大话设计模式 1 策略模式UML图 2 策略模式的概念 策略模式(Strategy) :它定义了算法家族,分别封装起来,让它们之间可以相互替换,此模式让算法的变化,不会影响到算法的客户。【DP】 3 策略模式和简单工厂模式的比较 简单工厂模式需要让客户端认识 两个类 ,而策略模式和简单工厂结合的用法,客户端就只需要认识 一个类 就可以了,耦合度更低。 4 策略模式解析 策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,他可以以相同的方式调用所有的算法,减少了
在Java多线程应用中,队列的使用率很高,多数生产消费模型的首选数据结构就是队列。Java提供的线程安全的Queue可以分为 阻塞队列和非阻塞队列 ,其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue,在实际应用中要根据实际需要选用阻塞队列或者非阻塞队列。 注:什么叫 线程安全 ?这个首先要明确。 线程安全的类  ,指的是 类内共享的全局变量的访问必须保证是 不受多线程形式影响的 。如果由于多线程的访问(比如修改、遍历、查看)而使这些变量结
偿还技术债 - 通过重构拯救老代码 尝试去接管一个陈旧的代码库使他成为达成一个可控的状态? 这几年的大型的旧web应用程序开发给了我们如下这些建议。 通过重构去拯救旧代码 松鼠会因为忘记自己把松果放在那里,使得每年多了几千棵松树。类似的,这些事情在项目中都没有什么关系。 你的项目是可以被拯救的 无论代码多么的杂乱,让人疯狂。 但是你的老板让你上了,你要相信不管前路多么曲折坎坷,你总能搞定的! 心无畏惧 公平的说。比起冲进一个四处鲜血还有巨龙守在门口的沼泽地待几年,你更愿意在一片清新的草原上散步。 不幸的是

hibernate缓存详解 - 2016-07-22 18:07:56

为什么要用hibernate缓存? hibernate是一个 持久层框架 ,经常访问物理数据库。为了降低应用程序对物理数据源访问的次数,从而提高应用程序的运行性能,我们想到使用hibernate缓存机制。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。 hibernate缓存的原理 缓存的主要作用是查询 。 hibernate缓存包括三大类: hibernate一级缓存、hibernate二级缓存和hibernate查询缓存 。 一