码迷,mamicode.com
首页 > 编程语言 > 详细

SpringAOP源码之 --- 增强

时间:2017-10-25 11:28:34      阅读:234      评论:0      收藏:0      [点我收藏+]

标签:nes   param   blog   ==   string   eof   pos   orb   apply   

概述

本章从下面几个方面来分析AOP的增强获取:

1、继续关系

2、增强的获取

从之前的入口一节介绍过,AOP的核心为AnnotationAwareAspectAutoProxyCreator,接下来来分析一下这个类,首先看继承关系:

技术分享

 

再看下类的层次关系,继承的类AbstractAutoProxyCreator,而AbstractAutoProxyCreator实现了BeanPostProcessor接口:

技术分享

BeanPostProcessor接口是干什么的呢?

如果我们想在bean实例化或其他配置初始化之前或之后要添加一些自己的处理,则如下定义一个实现了BeanPostProcessor接口的实现类,然后注册到Ioc容器中:

看下BeanPostProcessor的接口:

public interface BeanPostProcessor {

    
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

在AOP中,AbstractAutoProxyCreator实现了该接口,且实现了接口中的方法:

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName); //根据给定的bean和className构建cacheKey,形式为beanClassName_beanName
            if (!this.earlyProxyReferences.contains(cacheKey)) {
                return wrapIfNecessary(bean, beanName, cacheKey); //判断是否需要代理
            }
        }
        return bean;
    }


    /**
     * Build a cache key for the given bean class and bean name.
     * @param beanClass the bean class
     * @param beanName the bean name
     * @return the cache key for the given class and name
     */
    protected Object getCacheKey(Class<?> beanClass, String beanName) {
        return beanClass.getName() + "_" + beanName;
    }

    /**
     * Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
     * @param bean the raw bean instance
     * @param beanName the name of the bean
     * @param cacheKey the cache key for metadata access
     * @return a proxy wrapping the bean, or the raw bean instance as-is
     */
    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (beanName != null && this.targetSourcedBeans.contains(beanName)) {  //是否被处理过
            return 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;
        }

        // Create proxy if we have advice.
        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方法开始的,而AbstractAutoProxyCreator中的方法为抽象类,我们看具体的实现AbstractAdvisorAutoProxyCreator类

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
        List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
        if (advisors.isEmpty()) {
            return DO_NOT_PROXY;
        }
        return advisors.toArray();
    }

    /**
     * Find all eligible Advisors for auto-proxying this class.
     * @param beanClass the clazz to find advisors for
     * @param beanName the name of the currently proxied bean
     * @return the empty List, not {@code null},
     * if there are no pointcuts or interceptors
     * @see #findCandidateAdvisors
     * @see #sortAdvisors
     * @see #extendAdvisors
     */
    protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//最终为这两个方法 List
<Advisor> candidateAdvisors = findCandidateAdvisors(); //获取所有的增强 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); //增强中适用于bean的增强并应用 extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; }

findCandidateAdvisors(),寻找advisors,

AOP的配置
<aop:config proxy-target-class="true"> <aop:aspect ref="audience"> <aop:pointcut id="performance" expression="execution(* com.spring.test.action1.Performer.perform(..))"/> <aop:before pointcut-ref="performance" method="takeSeats"/> <aop:before pointcut-ref="performance" method="turnOffCellPhones"/> <aop:after-returning pointcut-ref="performance" method="applaud"/> <aop:after-throwing pointcut-ref="performance" method="demandRefund"/> </aop:aspect> </aop:config>

 

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( //获取所有的bean
                        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)) { //是否为合法的bean
                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;
    }

findAdvisorsThatCanApply()

 

SpringAOP源码之 --- 增强

标签:nes   param   blog   ==   string   eof   pos   orb   apply   

原文地址:http://www.cnblogs.com/dpains/p/7727346.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!