Spring的BeanPostProcessor执行顺序

BeanPostProcessor的五大接口,主要的11个回调方法

1.1顶层接口BeanPostProcessor
关于对象初始化前后的回调。

public interface BeanPostProcessor {
    //该方法在bean实例化完毕(且已经注入完毕),在afterPropertiesSet或自定义init方法执行之前
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    //在afterPropertiesSet或自定义init方法执行之后
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

1.2.InstantiationAwareBeanPostProcessor
关于对象实例化前后以及实例化后设置propertyValues的回调

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    //这个方法用来在对象实例化前直接返回一个对象(如代理对象)来代替通过内置的实例化流程创建对象;
    @Nullable
    default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    //在对象实例化完毕执行populateBean之前 如果返回false则spring不再对对应的bean实例进行自动依赖注入。
    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

//这里是在spring处理完默认的成员属性,应用到指定的bean之前进行回调,可以用来检查和修改属性,最终返回的PropertyValues会应用到bean中
    //@Autowired、@Resource等就是根据这个回调来实现最终注入依赖的属性的。
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return pvs;
    }
}

1.3.SmartInstantiationAwareBeanPostProcessor
这个接口主要是spring框架内部来使用

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    //用来返回目标对象的类型(比如代理对象通过raw class获取proxy type 用于类型匹配)
    @Nullable
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }
    //这里提供一个拓展点用来解析获取用来实例化的构造器(比如未通过bean定义构造器以及参数的情况下,会根据这个回调来确定构造器)
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {
        return null;
    }
    //获取要提前暴露的bean的引用,用来支持单例对象的循环引用(一般是bean自身,如果是代理对象则需要取用代理引用)
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }
}


1.4.MergedBeanDefinitionPostProcessor
用来将merged BeanDefinition暴露出来的回调

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
    //在bean实例化完毕后调用 可以用来修改merged BeanDefinition的一些properties 或者用来给后续回调中缓存一些meta信息使用
    //这个算是将merged BeanDefinition暴露出来的一个回调
    void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}

1.5.DestructionAwareBeanPostProcessor
关于处理对象销毁的前置回调
应用实例:
ApplicationListenerDetector,这个类是用来注册ApplicationListener实例的,而如果销毁一个对象,不接触这里的引用,会导致无法进行回收,因此在销毁对象时,会判断如果是ApplicationListener要执行从监听器列表中移除掉。

public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
    //这里实现销毁对象的逻辑
    void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
    //判断是否需要处理这个对象的销毁
    default boolean requiresDestruction(Object bean) {
        return true;
    }
}

关于这些方法的回调顺序

1>>>>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
2>>>>SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors
3>>>>MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
4>>>>InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
6>>>>BeanPostProcessor.postProcessBeforeInitialization
7>>>>BeanPostProcessor.postProcessAfterInitialization
8>>>>DestructionAwareBeanPostProcessor.postProcessBeforeDestruction


1、InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(beanClass, beanName)
该方法在创建对象之前会先掉用,如果有返回实例则直接使用不会去走下面创建对象的逻辑,并在之后执行
BeanPostProcessor.postProcessAfterInitialization(result, beanName)
2、SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors(beanClass, beanName)
如果需要的话,会在实例化对象之前执行
3、MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(mbd, beanType, beanName)
在对象实例化完毕 初始化之前执行
4、InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)
在bean创建完毕初始化之前执行
5、InstantiationAwareBeanPostProcessor.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName)
在bean的property属性注入完毕 向bean中设置属性之前执行
6、BeanPostProcessor.postProcessBeforeInitialization(result, beanName)
在bean初始化(自定义init或者是实现了InitializingBean.afterPropertiesSet())之前执行
7、BeanPostProcessor.postProcessAfterInitialization(result, beanName)
在bean初始化(自定义init或者是实现了InitializingBean.afterPropertiesSet())之后执行
8、其中DestructionAwareBeanPostProcessor方法的postProcessBeforeDestruction(Object bean, String beanName)会在销毁对象前执行
DestructionAwareBeanPostProcessor 中的requiresDestruction(Object bean)是用来判断是否属于当前processor处理的bean
SmartInstantiationAwareBeanPostProcessor中的predictBeanType(Class<?> beanClass, String beanName)是用来预判类型的
SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference(exposedObject, beanName)
这个方法仅仅是在这一步是作为一个ObjectFactory封装起来放到singletonFactories中的,
仅在并发情况下 刚好在当前对象设置进去,而另一个bean创建需要getBean获取时才会立即执行
因此这一步的顺序是不一定的,有可能永远不会执行(无并发循坏依赖对象创建的场景)
可能在3之后对象实例化完毕执行addSingleton(beanName, singletonObject);之前执行到
因此这三个方法没有严格的顺序意义


验证代码如下:

/**
 * com.yjm
 * Created by YJM6280 .
 */
@Configuration
public class SpringLifeCycle {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringLifeCycle.class);
        context.registerBeanDefinition("demoBean",new RootBeanDefinition(DemoBean.class));
        context.getBean("demoBean");
        context.start();
        context.destroy();
    }
    public  static  class DemoBean{

    }
    @Bean
    public  BeanPostProcessor fullyBeanPostProcessor(){
        return  new FullyBeanPostProcessor();
    }
    @Order
    public  class  FullyBeanPostProcessor implements BeanPostProcessor,
            InstantiationAwareBeanPostProcessor,
            SmartInstantiationAwareBeanPostProcessor,
            MergedBeanDefinitionPostProcessor,
            DestructionAwareBeanPostProcessor{
        @Nullable
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if(beanClass == DemoBean.class){
                System.out.println("1>>>>InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
            }
            return null;
        }

        @Nullable
        @Override
        public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
            if(beanClass == DemoBean.class) {
                System.out.println("2>>>>SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors");
            }
            return null;
        }

        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
             if(beanType == DemoBean.class){
                 System.out.println("3>>>>MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition");
             }
        }

        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if(bean instanceof  DemoBean){
                System.out.println("4>>>>InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
            }
            return false;
        }

        @Nullable
        @Override
        public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
            if(bean instanceof  DemoBean){
                System.out.println("5>>>>InstantiationAwareBeanPostProcessor.postProcessPropertyValues");
            }
            return null;
        }
        @Nullable
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if(bean instanceof  DemoBean){
                System.out.println("6>>>>BeanPostProcessor.postProcessBeforeInitialization");
            }
            return null;
        }

        @Nullable
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if(bean instanceof  DemoBean){
                System.out.println("7>>>>BeanPostProcessor.postProcessAfterInitialization");
            }
            return null;
        }

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

推荐阅读更多精彩内容

  • IOC和DI是什么? Spring IOC 的理解,其初始化过程? BeanFactory 和 FactoryBe...
    justlpf阅读 3,475评论 1 21
  • 本来是准备看一看Spring源码的。然后在知乎上看到来一个帖子,说有一群**自己连Spring官方文档都没有完全读...
    此鱼不得水阅读 6,935评论 4 21
  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 12,294评论 6 86
  • 2.1 我们的理念是:让别人为你服务 IoC是随着近年来轻量级容器(Lightweight Container)的...
    好好学习Sun阅读 2,715评论 0 11
  • 今天的天气闷沉,不用去教研室值班,莎伦睡到9点。 从宿舍天窗里传进来自水房漱漱的流水声,女孩咯咯的笑着讨论着待会儿...
    莎伦小姐阅读 209评论 0 0