Sping源码(七)— CustomBeanFactoryPostProcessor

扩展(一):自定义BFPP

上一篇讲invokeBeanFactoryPostProcessor()方法逻辑时说到了beanFactoryPostProcessors参数,会在方法调用时优先进行处理,并且里面都是继承了BeanDefinitionRegistryPostProcessor的自定义扩展类。

本篇会介绍如何扩展自定义的BeanDefinitionRegistryPostProcessor类。

invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

先来看看getBeanFactoryPostProcessors()方法。

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext {
	//方法直接return类中beanFactoryPostProcessors属性值 
	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}
	//有get就会有add(set)
	@Override
	public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
		this.beanFactoryPostProcessors.add(postProcessor);
	}

那么我们只要自定义类,继承AbstractApplicationContext 类并实现addBeanFactoryPostProcessor()方法将我们自定义的类加进去即可。

自定义ApplicationContext

自定义ApplicationContext继承ClassPathXmlApplicationContext ,并重写customizeBeanFactory方法,显式调用addBeanFactoryPostProcessor(),将我们自定义的MyCustomBFPP添加进去。

public class MyCustomApplicationContext extends ClassPathXmlApplicationContext {

    public MyCustomApplicationContext(String... configLocations) throws BeansException {
        super(configLocations);
    }

    @Override
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        super.addBeanFactoryPostProcessor(new MyCustomBFPP());
    }

}

类关系图
在这里插入图片描述

自定义BFPP

自定义的MyCustomBFPP 实现了BeanFactoryPostProcessor 类,

public class MyCustomBFPP implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyCustomBDRPP.postProcessBeanFactory");
    }

main

使用我们自定义的ApplicationContext加载xml文件,那么在执行customizeBeanFactory方法时,就会将我们自定义的MyCustomBFPP加进去,此时在invokeBeanFactoryPostProcessors()方法的beanFactoryPostProcessors参数中,就会看到我们的扩展类

public class Test {

    public static void main(String[] args) {

        MyCustomApplicationContext ac = new MyCustomApplicationContext("applicationContext.xml");

    }
}

在这里插入图片描述

扩展(二):getBeanNamesForType

上一篇介绍invokeBeanFactoryPostProcessors()方法整体执行流程时,方法内多次调用getBeanNamesForType()方法,每次都重新获取所有BeanDefinitionRegistryPostProcessor接口的bean的beanName。

目的是为了防止在上一步执行postProcessBeanDefinitionRegistry方法后,产生新的BDRPP类 。

举个栗子:自定义一个类,这个类有如下要求

  1. 继承BeanDefinitionRegistryPostProcessor重写postProcessBeanDefinitionRegistry()方法
  2. 在postProcessBeanDefinitionRegistry()方法中,生成新的、同样继承了BeanDefinitionRegistryPostProcessor的类。
  3. 自定义的类可以让Spring识别管理。

在xml中通过bean标签的形式,可以让Spring加载xml时进行解析封装成Definition并注册到BeanFacroty。

xml中声明

<bean class="com.xxx.bdrpp.CustomBDRPP"></bean>

自定义BDRPP

自定义BDRPP,实现BeanDefinitionRegistryPostProcessor重写postProcessBeanDefinitionRegistry()时,声明了RootBeanDefinition并在构造方法中传入要生成的CustomRegistryBDRPP.class。
同时实现PriorityOrdered 类是为了在源码中可以优先执行。

public class CustomBDRPP implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("CustomBDRPP.postProcessBeanFactory");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
       //写法1
       //BeanDefinitionBuilder bdb = BeanDefinitionBuilder.rootBeanDefinition(CustomRegistryBDRPP.class);
       //registry.registerBeanDefinition("myCustom",bdb.getBeanDefinition());
      
        //写法2
        registry.registerBeanDefinition("myCustom",new RootBeanDefinition(CustomRegistryBDRPP.class));
        // 无论写法1还是写法2, 都是相当于将CustomRegistryBDRPP封装进Definition,并注册到BeanFactory的beanDefinitionMap和beanDefinitionNames中
        System.out.println("CustomBDRPP.postProcessBeanDefinitionRegistry");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

要在postProcessBeanDefinitionRegistry方法中新加入的CustomRegistryBDRPP。

public class CustomRegistryBDRPP implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("CustomRegistryBDRPP----postProcessBeanFactory");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("CustomRegistryBDRPP----postProcessBeanDefinitionRegistry");
    }
}

接下来,我们来看一下执行流程,Spring是如何解析的CustomBDRPP 以及在执行postProcessBeanDefinitionRegistry方法时是如何识别到CustomRegistryBDRPP的。

执行流程

在这里插入图片描述

源码片段

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
            
            // 用于保存本次要执行的BeanDefinitionRegistryPostProcessor
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

            // 调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类
            // 找到所有实现BeanDefinitionRegistryPostProcessor接口bean的beanName
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            // 遍历处理所有符合规则的postProcessorNames
            for (String ppName : postProcessorNames) {
                // 检测是否实现了PriorityOrdered接口
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 获取名字对应的bean实例,添加到currentRegistryProcessors中
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    // 将要被执行的BFPP名称添加到processedBeans,避免后续重复执行
                    processedBeans.add(ppName);
                }
            }
            // 按照优先级进行排序操作
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            // 添加到registryProcessors中,用于最后执行postProcessBeanFactory方法
            registryProcessors.addAll(currentRegistryProcessors);
            // 遍历currentRegistryProcessors,执行postProcessBeanDefinitionRegistry方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            // 执行完毕之后,清空currentRegistryProcessors
            currentRegistryProcessors.clear();
            
            //再次获取实现BeanDefinitionRegistryPostProcessor的BeanName
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
    }

而当CustomBDRPP类执行完invokeBeanDefinitionRegistryPostProcessors()方法时,方法的底层逻辑会将自定义的CustomRegistryBDRPP封装进Definition,并注册到BeanFactorybeanDefinitionMapbeanDefinitionNames

此时再次调用getBeanNamesForType(),就可以获取到我们通过invokeBeanDefinitionRegistryPostProcessors方法创建的CustomRegistryBDRPP

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值