6.SpringAop之声明式Aop基于配置:DefaultAdvisorAutoProxyCreator

这个类的设计,和Spring ioc的结合,简直是吊炸天,实现了根据配置把spring ioc里面的bean替换为相应的代理对象,也为AspectJ的整合提供了支持,让我们来看看Spring是如何做到这种更高级的声明式Aop

1.类结构

DefaultAdvisorAutoProxyCreator类结构

这边的讲解线路分为2块

  1. Spring的Bean后处理器,SmartInstantiationAwareBeanPostProcessor->InstantiationAwareBeanPostProcessor->BeanPostProcessor
  2. DefaultAdvisorAutoProxyCreator的主继承线,DefaultAdvisorAutoProxyCreator->AbstractAdvisorAutoProxyCreator->AbstractAutoProxyCreator->ProxyProcessorSupport->ProxyConfig

讲解之前可以看下我写的这块的demo ,可以一边看解析,一边打断点调试

2.解析

2.1 Spring Bean后处理器

在讲这三个接口之前,我们先来看下Spring bean的生命周期,不知道这个流程,也很难理解这三个接口的作用
阅读AbstractAutowireCapableBeanFactory的doCreateBean和destroyBean方法,我们能清楚看到Spring bean创建的整个生命周期,具体如下

  1. 调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
  2. bean实例化
  3. 调用InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation(Object bean, String beanName)
  4. 调用InstantiationAwareBeanPostProcessor的postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
  5. bean注入properties
  6. 分别调用BeanNameAware,BeanClassLoaderAware,BeanFactoryAware中的方法
  7. 调用BeanPostProcessor的postProcessBeforeInitialization(Object bean, String beanName)
  8. 调用InitializingBean的afterPropertiesSet方法
  9. 调用自定义初始化方法
  10. 调用BeanPostProcessor的postProcessAfterInitialization(Object bean, String beanName)
  11. 调用DisposableBean的destroy()方法
  12. 调用自定义销毁方法

下面分别介绍这三个bean后处理器的功能

public interface BeanPostProcessor {

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

从生命周期中可以看到,BeanPostProcessor中的这两个方法分别会在bean调用init方法前后回调,用于对已经注入properties的bean对象进行修改,把bean替换成代理对象会在postProcessAfterInitialization中执行

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

    PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}

postProcessBeforeInstantiation和postProcessAfterInstantiation分别在bean实例化前后回调
postProcessPropertyValues将在注入properties之前触发,可以对整理好的properties进行修改

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;

    Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;

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

}

predictBeanType用于提前给出postProcessBeforeInstantiation生成的bean的类型
determineCandidateConstructors用于bean初始化的时候决定调用哪一个构造函数,如果针对某个类型的bean设置了这个回调,会采用回调设置的构造函数初始化bean,具体逻辑代码如下

Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

getEarlyBeanReference用于解决循环依赖的问题

这三个bean后处理器讲解好了 ,现在我们开始讲DefaultAdvisorAutoProxyCreator是怎么实现自动配置代理对象的

2.2 DefaultAdvisorAutoProxyCreator

从类结构图中可以看到主要的继承链,DefaultAdvisorAutoProxyCreator->AbstractAdivisorAutoProxyCreator->AbstractAutoProxyCreator->ProxyProcessorSupport->ProxyConfig
ProxyConfig就不多讲了,之前讲过,我们来分别介绍下其他4个类的作用

2.2.1 ProxyProcessorSupport

看名字就知道是一个为代理生成提供支持的工具类,主要提供evaluateProxyInterfaces方法用来根据BeanClass对ProxyFactory中的代理方式进行配置,方法如下

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
        Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
        boolean hasReasonableProxyInterface = false;
        for (Class<?> ifc : targetInterfaces) {
            if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
                    ifc.getMethods().length > 0) {
                hasReasonableProxyInterface = true;
                break;
            }
        }
        if (hasReasonableProxyInterface) {
            // Must allow for introductions; can't just set interfaces to the target's interfaces only.
            for (Class<?> ifc : targetInterfaces) {
                proxyFactory.addInterface(ifc);
            }
        }
        else {
            proxyFactory.setProxyTargetClass(true);
        }
    }

这里会判断是否可以代理接口,如果可以,用proxyFactory的addInterface方法把设置所有存在的接口类,如果不可以,那么调用setProxyTargetClass(true),配置为代理类
同时我们可以注意到这个类实现了Ordered接口,并且设置order = Ordered.LOWEST_PRECEDENCE,这是为了让生成代理的后处理器最后一个执行(原因可能是在之前的后处理器可能也会把Advisor加进去,那样就会出现不生效的问题)

2.2.2 AbstractAutoProxyCreator

这个类是这个继承链中最核心的类,因为生成代理的逻辑封装在这里
它实现SmartInstantiationAwareBeanPostProcessor,在回调方法里封装了把bean对象替换为代理对象的逻辑,在getEarlyBeanReference,postProcessBeforeInstantiation,postProcessAfterInitialization均能产生代理,postProcessBeforeInstantiation需要在配置了TargetSourceCreator之后才能生效,目前没有遇到这个场景,所以忽略,getEarlyBeanReference是为了解决循环依赖重写的,用来提前长生代理类,postProcessAfterInitialization在getEarlyBeanReference没有生效的情况下会被调用,这两个方法都调用了wrapIfNecessary来生成代理,我们来看下这个方法

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;
    }

wrapIfNecessary首先会通过getAdvicesAndAdvisorsForBean得到拦截器集合,这个会交给子类实现,子类可以设计不同的策略来获取拦截器集合,如果getAdvicesAndAdvisorsForBean返回的集合不为空,就调用createProxy生成代理

protected Object createProxy(
            Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

        if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
            AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
        }

        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.copyFrom(this);

        if (!proxyFactory.isProxyTargetClass()) {
            if (shouldProxyTargetClass(beanClass, beanName)) {
                proxyFactory.setProxyTargetClass(true);
            }
            else {
                evaluateProxyInterfaces(beanClass, proxyFactory);
            }
        }

        Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
        proxyFactory.addAdvisors(advisors);
        proxyFactory.setTargetSource(targetSource);
        customizeProxyFactory(proxyFactory);

        proxyFactory.setFrozen(this.freezeProxy);
        if (advisorsPreFiltered()) {
            proxyFactory.setPreFiltered(true);
        }

        return proxyFactory.getProxy(getProxyClassLoader());
    }

createProxy还是比较熟悉的,在上节铺垫过,使用了ProxyFactory的编程式Aop生成代理
通过这几个回调,巧妙的在spring生命周期内把我们生成代理bean的行为注入了

2.2.3 AbstractAdivisorAutoProxyCreator

AbstractAdivisorAutoProxyCreator主要实现了AbstractAutoProxyCreator提供的扩展点方法getAdvicesAndAdvisorsForBean,用来设置拦截器集合

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();
    }

getAdvicesAndAdvisorsForBean中会通过findEligibleAdvisors来获取拦截器集合,如果不存在返回DO_NOT_PROXY,来看下findEligibleAdvisors

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;
    }

protected List<Advisor> findCandidateAdvisors() {
        return this.advisorRetrievalHelper.findAdvisorBeans();
    }

在findEligibleAdvisors中,通过findCandidateAdvisors来获取候选的adivisors,内部使用了advisorRetrievalHelper.findAdvisorBeans,其实就是从beanfactory获取实现Advisor接口的bean,然后可以在这个方法里面看到

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;
    }

注意到有一个isEligibleBean方法,在AbstractAdivisorAutoProxyCreator使用了BeanFactoryAdvisorRetrievalHelper扩展子类,重定义了isEligibleBean方法,如下

private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {

        public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
            super(beanFactory);
        }

        @Override
        protected boolean isEligibleBean(String beanName) {
            return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
        }
    }

把BeanFactoryAdvisorRetrievalHelper中的isEligibleBean委托给了AbstractAdvisorAutoProxyCreator实现,AbstractAdvisorAutoProxyCreator中默认实现如下

protected boolean isEligibleAdvisorBean(String beanName) {
        return true;
    }

这个实现默认为不过滤,可以让子类去实现

2.2.4 DefaultAdvisorAutoProxyCreator

DefaultAdvisorAutoProxyCreator实现AbstractAdivisorAutoProxyCreator开放的扩展点isEligibleAdvisorBean,逻辑很简单,如下

protected boolean isEligibleAdvisorBean(String beanName) {
        return (!isUsePrefix() || beanName.startsWith(getAdvisorBeanNamePrefix()));
    }

通过配置的prefix来过滤adivisor bean

2.3 InfrastructureAdvisorAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator

InfrastructureAdvisorAutoProxyCreator也实现了AbstractAdivisorAutoProxyCreator开放的扩展点isEligibleAdvisorBean

@Override
   protected boolean isEligibleAdvisorBean(String beanName) {
       return (this.beanFactory.containsBeanDefinition(beanName) &&
               this.beanFactory.getBeanDefinition(beanName).getRole() == BeanDefinition.ROLE_INFRASTRUCTURE);
   }

可以看到,这个过滤条件是,只选择框架级别(beanDefinitiod的role为ROLE_INFRASTRUCTURE)的Adivisor来进行对符合条件的对象进行织入,生成代理

3.总结

DefaultAdvisorAutoProxyCreator主要实现的功能为使用bean后处理器的回调函数,根据ioc容器配置的advisor,来对ioc 容器中的其他bean生成相应代理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 如下是整篇文章的结构,所需阅读时间大约20min Spring简介 Spring框架由Rod Johnson开发,...
    李序锴阅读 892评论 0 15
  • Spring框架是由于软件开发的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由EJB...
    OSET我要编程阅读 2,703评论 0 3
  • 昨天,和妈吵了一小架。一开始很生气,唉!才说要好好陪她的。上班后想了想觉得真是对不起她老人家,不论妈怎么想...
    梁正妈妈阅读 314评论 0 8
  • 前面介绍的组合继承最大的问题就是无论什么情况下,都会调用两次父类型的构造函数:一次是在创建子类型原型的时候,另一次...
    赵者也阅读 320评论 0 0