spring-BeanFactoryPostProcessor/BeanDefinitionRegistryPostProcessor扩展使用【有使用方法还有原理】

1、首先看自定义的BeanFactoryPostProcessor/BeanDefinitionRegistryPostProcessor执行链路【都是一样的他们】

    1)、BeanDefinitionRegistryPostProcessor执行时在BeanFactoryPostProcessor之前

    2)、PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法里面完成的

  • BeanDefinitionRegistryPostProcessor的执行顺序优先于BeanFactoryPostProcessor

2、调用流程

BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor都是在这里被处理的流程一模一样
AnnotationConfigApplicationContext
 --》初始化方法(构造函数)
   --》refresh
     --》invokeBeanFactoryPostProcessors(beanFactory)调用BeanFactoryPostProcessor
		--》PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())
		    PostProcessorRegistrationDelegate类中的方法
			--》invokeBeanFactoryPostProcessors内部执行逻辑
				1)、在beanFactory中查找BeanDefinitionRegistryPostProcessor.class类型的bean定义,找出来【得到一个List】
					1)、拿到List集合调用了beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class/BeanFactoryPostProcessor)【完成了bean的实例化动作】
				2)、看看是否实现了PriorityOrdered接口(优先级较高的排序)beanFactory.isTypeMatch(ppName, PriorityOrdered.class)【筛选后的List01】
				3)、看看是否实现了Ordered接口(排序低于PriorityOrdered) beanFactory.isTypeMatch(ppName, Ordered.class)【筛选后的List02】
				4)、剩下的就是普通的BeanFactoryPostProcessor,没有实现任何排序接口的【筛选后的List03】
				3)、invokeBeanDefinitionRegistryPostProcessors调用【筛选后的List01--03】分别各自调用这个接口(List为输入参数)
					1)、拿到上面List参数循环,由于List里面就是具体
					2)、BeanDefinitionRegistryPostProcessor--调用这个方法postProcessBeanDefinitionRegistry(registry)//参数其实就是beanFactory
						BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory,只是通过这种方式转化了一下而已
					3)、BeanFactoryPostProcessor--调用这个方法postProcessBeanFactory(beanFactory)
						到这里就实现了对MyBeanFactoryPostProcessor自定义BeanFactoryPostProcessor方法postProcessBeanFactory进行调用

3、自定义的BeanFactoryPostProcessor

MyBeanFactoryPostProcessor
//一定要定义为组件,让spring容器加载,否则spring容器就无法识别
@Component
public class MyBeanFactoryPostProcessor implements 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.
     * 翻译:
     *   在应用程序spring上下文内部的bean工厂完成初始化以后提供其修改功能
     *   所有的bean定义都已经加载完毕,但是这些bean都还被实例化。这个时候允许重新覆盖(原来已加载的bean定义)
     *   或者甚至可以给bean定义添加属性
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor--postProcessBeanFactory");
        /**
         * 1、把已经定义的beanName找出来,把对应的beanClass进行替换
         *   如下把wolfBean已经定义的WolfBean.class修改成SunBean.class
         */
        RootBeanDefinition beanDefinition = (RootBeanDefinition) beanFactory.getBeanDefinition("wolfBean");
        beanDefinition.setBeanClass(SunBean.class);
        /**
         * 2、给beanFactory容器注册一个单例bean,名称和Object
         */
        beanFactory.registerSingleton("god",new Dog()); //通过反射的方式实例化
    }
}

6、自定义BeanDefinitionRegistryPostProcessor 

@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    /**
     * 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.
     * 翻译:
     * 1、允许修改spring容器里面的bean定义,在标准初始化之后;所有合法的bean定义将要被加载,
     * 但是没有Bean被实例化。这允许我们
     * 他的意见允许进一步增加
     * <p>
     * 在下一个后期处理阶段开始之前定义bean
     *
     * @param registry the bean definition registry used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor---postProcessBeanDefinitionRegistry");
        int count = registry.getBeanDefinitionCount();
        System.out.println("bean 定义数量为" + count);
        String[] beanDefinitionNames = registry.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(PersonDao.class);
        registry.registerBeanDefinition("PersonDao", beanDefinition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }
}

5、执行类

@Configuration//定义为配置类
@ComponentScan("com.extend")//扫描加上,不然组件等信息就无法被spring容器加载
public class MyBeanFactoryPostProcessorTest{

    /**
     * 扩展原理分析参考
     * BeanPostProcessor bean的后置处理器
     * 1、在bean创建对象初始化之前和之后执行相关业务,以实现对bean的增强
     * BeanFactoryPostProcessor beanFactory的后置处理器
     * 2、BeanDefinitionRegistryPostProcessor bean定义注册后置处理器
     *
     * 1、在beanFactory初始化之后进行调用,这样可以实现对beanFactory里面定义的beanDefinition修改和扩展
     *    这个时候所有的bean定义都被加载完毕,但是bean还没有创建
     * 2、BeanFactoryPostProcessor实现原理
     *    先断点到自定义的BeanFactoryPostProcessor,看看代码执行链路
     *    1)、
     * @param args
     */
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyBeanFactoryPostProcessorTest.class);
        System.out.println(JSON.toJSONString(context.getBeanDefinitionNames()));
    }

    @Bean
    WolfBean wolfBean(){
        return new WolfBean();
    }
}

后记

先看看DefaultListableBeanFactory类图结构

Spring容器及其他第三方开源框架基于这个的实现

  • BeanDefinitionRegistryPostProcessor

  • BeanFactoryPostProcessor

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值