美文网首页
【Spring源码】5.IOC之BeanFactoryPostP

【Spring源码】5.IOC之BeanFactoryPostP

作者: 天还下着毛毛雨 | 来源:发表于2022-01-15 15:48 被阅读0次

    概述

    在spring-ioc核心方法中,创建BeanFactory以及解析xml配置文件的方法之后,接下来还有一个重要的方法 invokeBeanFactoryPostProcessors(beanFactory);

    image

    这个方法 会 取出 IOC容器里 所有实现了BeanDefinitionRegistryPostProcessor接口和BeanFactoryPostProcessor接口的BeanNames, 然后实例化,分别调用

    1. 实现自BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法。
    2. 实现自BeanFactoryPostProcessor postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法。

    注意,同BeanPostProcessor接口实例不同, 这两个接口的实例,只会在 所有常规Bean,生成BeanDefinition之后,Bean真正实例化之前被调用一次。而BeanPostProcessor接口实例 在每一个Bean的实例化过程中 都会被依次调用。

    BeanFactoryPostProcessor接口

    @FunctionalInterface
    public interface BeanFactoryPostProcessor {
    
       /**
        * Modify the application context's internal bean factory after its standard
        * initialization. All bean definitions will have been loaded, but no beans
        * will have been instantiated yet. This allows for overriding or adding
        * properties even to eager-initializing beans.
        * @param beanFactory the bean factory used by the application context
        * @throws org.springframework.beans.BeansException in case of errors
        */
       void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    
    }
    

    方法入参 可以拿到beanFactory实例, 利用该对象提供的api可以对容器里的bean进行一些操作。

    BeanDefinitionRegistryPostProcessor接口

    public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    
       /**
        * Modify the application context's internal bean definition registry after its
        * standard initialization. All regular bean definitions will have been loaded,
        * but no beans will have been instantiated yet. This allows for adding further
        * bean definitions before the next post-processing phase kicks in.
        * @param registry the bean definition registry used by the application context
        * @throws org.springframework.beans.BeansException in case of errors
        */
       void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
    
    }
    

    BeanDefinitionRegistryPostProcessor 接口实现了BeanFactoryPostProcessor, 那么实现BeanDefinitionRegistryPostProcessor 就可以实现两个接口对应的方法,同时拿到

    BeanFactory和BeanDefinitionRegistry实例。

    应用

    自己声明一个类,实现BeanDefinitionRegistryPostProcessor接口, 就会在该阶段被调用对应方法,拿到入参BeanDefinitionRegistry,BeanFactory实例,在Bean实例化之前 对容器里的BeanDefinition做增删改查,操作Bean等等。

    @Component
    public class Bfp implements BeanDefinitionRegistryPostProcessor {
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            // 注册BeanDefinition
            registry.registerBeanDefinition();
            // 删除
            registry.removeBeanDefinition();
            // 拿到所有beanDefinitionName
            for (String beanDefinitionName : registry.getBeanDefinitionNames()) {
                BeanDefinition beanDefinition = registry.getBeanDefinition(beanDefinitionName);
                // 修改beanDefinition
                beanDefinition.setDependsOn();
            }
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            // 提前实例化bean
            beanFactory.getBean("beanName");
            // 注册自定义bean作用域
            beanFactory.registerScope("aa", new Scope() {
                @Override
                public Object get(String name, ObjectFactory<?> objectFactory) {
                }
    
                @Override
                public Object remove(String name) {
                    return null;
                }
    
                @Override
                public void registerDestructionCallback(String name, Runnable callback) {
    
                }
    
                @Override
                public Object resolveContextualObject(String key) {
                    return null;
                }
    
                @Override
                public String getConversationId() {
                    return null;
                }
            });
        }
    }
    

    调用流程解析

    1.BeanDefinitionRegistryPostProcessor接口的调用

    点进该方法

    image

    getBeanFactoryPostProcessors() 会从上下文内部的beanFactoryPostProcessors容器里拿,这个时候是空的。

    image

    1.1. 先调用已有的getBeanFactoryPostProcessors()已有的实例

    image

    由于容器刚开始没有值,这个时候可以跳过。

    2.再调用实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor类型实例的方法

    image

    先取出BeanDefinitionRegistryPostProcessor类型的BeanName集合,判断是不是实现了PriorityOrdered接口,是的话先实例化, 然后按照PriorityOrdered接口排序,

    最终调用postProcessBeanDefinitionRegistry方法。

    image

    3. 再调用实现Ordered接口的BeanDefinitionRegistryPostProcessor类型实例的方法

    image

    和上面的流程一样,没被处理过的,先实例化,然后按照Ordered接口排序,然后调用它的postProcessBeanDefinitionRegistry方法。

    4.再调用没实现以上两种排序接口的实例

    [图片上传失败...(image-e19b4d-1642232833930)]

    5.最后按照排序优先级,调用实现自BeanFactoryPostProcessor接口的postProcessBeanFactory方法

    image image

    2.BeanFactoryPostProcessor接口实例的调用

    对只实现了BeanFactoryPostProcessor接口的实例进行调用,流程和调用BeanDefinitionRegistryPostProcessor实例 一样:

    1. 取出BeanFactoryPostProcessord的BeanNames
    2. 按排序接口优先级,先实例化
    3. 再调用BeanFactoryPostProcessor接口的postProcessBeanFactory方法。
    image

    总结:

    1.BeanDefinitionRegistryPostProcessor类的调用

    1. 首先从BeanDifinition中获取到所有BeanDefinitionRegistryPostProcessor类的bean
    2. 判断时候实现PriorityOrdered,有的话,实例化,加入的容器中
    3. 对容器中的bean进行排序,然后调用bean的postProcessBeanDefinitionRegistry
    4. 清空容器
    5. 判断时候实现Order接口,有的话,实例化,加入的容器中
    6. 对容器中的bean进行排序,然后调用bean的postProcessBeanDefinitionRegistry方法
    7. 清空容器
    8. 接下来是对没有实现排序接口的BeanDefinitionRegistryPostProcessor进行实例化
    9. 循环bean,然后调用bean的postProcessBeanDefinitionRegistry方法

    2.BeanFactoryPostProcessor类的调用

    同 BeanDefinitionRegistryPostProcessor类的调用逻辑是一样的,都是排序,实例化,调用postProcessBeanFactory方法

    注意点:

    实现这两个接口的类会在这里就已经触发getBean的操作,就是实例化,实现的方法会传入beanDefinitionRegistry和beanFactory对象

    beanDefinitionRegistry可以在实现的方法里面对beanDefinition进行修改和新增,可以在这里自己创建beanDefinition加入到它里面的容器中,后续会实例化

    beanFactory ,可以直接对bean进行操作

    相关文章

      网友评论

          本文标题:【Spring源码】5.IOC之BeanFactoryPostP

          本文链接:https://www.haomeiwen.com/subject/pywthrtx.html