【Spring 源码】ApplicationContext 容器的加载原理(三)

【Spring 源码】ApplicationContext 容器的加载原理(三)



一、BeanFactory 的后处理

(一) 调用 BeanFactoryPostProcessors

1. 使用 PropertyPlaceholderConfigurer

BeanFactoryPostProcessors 的经典例子就是使用 PropertyPlaceholderConfigurer,在平常使用 Spring 的时候经常能看到 xml 里面配置了 ${...} 这种变量引用,而实际调用的值则在 property 文件中。

比如在 xml 文件中使用了 ${bean.id} 变量引用,而 property 中则配置了 bean.id=12345,这样过把整个 bean 打印出来,则可以打印出整个 bean 的内容来。

【1】配置方法

当然如果使用需要指定 property 文件的位置,而指定的方式有两种:

  1. 使用 context 标签的方式
    此方法会默认使用 PropertySourcesPlaceholderConfigurer 来进行对 ${...} 占位符的解析。
<context:property-placeholder location="/configs/bean.properties"/>
  1. 普通 bean 的注册方式
    此方法可以指定调用的类,在这边指定了 PropertyPlaceholderConfigurer,而如果是第一种方式,则会默认使用 PropertySourcesPlaceholderConfigurer。
<bean id="config" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="location">  
        <value>/configs/bean.properties</value>  
    </property>
</bean>
【2】简单例子
  • 目录结构:
|-- src.main
	|-- java.com.test
		|-- Main.java
		|-- MyBean.java
	|-- resources
	    |-- configs
	        |-- bean.properties
	    |-- MyBean.xml
  • MyBean.java:
public class MyBean {  
  
    private Integer beanId;  
  
    private String message;  
  
    private Double price;  
  
    public Integer getBeanId() {  
        return beanId;  
    }  
  
    public void setBeanId(Integer beanId) {  
        this.beanId = beanId;  
    }  
  
    public String getMessage() {  
        return message;  
    }  
  
    public void setMessage(String message) {  
        this.message = message;  
    }  
  
    public Double getPrice() {  
        return price;  
    }  
  
    public void setPrice(Double price) {  
        this.price = price;  
    }  
  
    @Override  
    public String toString() {  
        return "MyBean{" +  
                "beanId=" + beanId +  
                ", message='" + message + '\'' +  
                ", price=" + price +  
                '}';  
    }  
}
  • MyBean.xml:
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">  
  
	<bean id="myBean" class="com.test.MyBean">  
	    <property name="message" value="#{'Hello World!'}" />  
	    <property name="price" value="#{10.1 + 20}" />  
	    <property name="beanId">  
	        <value>${bean.id}</value>  
	    </property>
	</bean>  
  
	<bean id="config" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
	    <property name="location">  
	        <value>/configs/bean.properties</value>  
	    </property>
    </bean>
</beans>
  • Main.java:
public class Main {

    public static void main(String[] args) {
        XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("MyBean.xml"));
        MyBean bean = (MyBean) beanFactory.getBean("myBean");
  
        System.out.println(bean.toString());
    }  
}
  • bean.property:
bean.id=12345
  • 结果:
MyBean{beanId=12345, message='Hello World!', price=30.1}

2. PropertyPlaceholderConfigurer 加载原理

【1】加载过程时序图

在 invokeBeanFactoryPostProcessors 加载过程中其实主要是设计到三个步骤:

  • 获取 BeanDefinitionRegistryPostProcessor 或者 BeanFactoryPostProcessor 类型的 bean。
  • 然后再对 bean 进行排序。
  • 最后调用 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry() 或者 BeanFactoryPostProcessor 的 postProcessBeanFactory()
AbstractApplicationContext PostProcessorRegistrationDelegate PropertyResourceConfigurer PropertyPlaceholderConfigurer PlaceholderConfigurerSupport refresh() invokeBeanFactoryPostProcessors() invokeBeanFactoryPostProcessors() mergeProperties() convertProperties() processProperties() par [postProcessBeanFactory()] doProcessProperties() AbstractApplicationContext PostProcessorRegistrationDelegate PropertyResourceConfigurer PropertyPlaceholderConfigurer PlaceholderConfigurerSupport
【2】加载过程源码

invokeBeanFactoryPostProcessors() 方法中会涉及到 BeanDefinitionRegistryPostProcessor 或者 BeanFactoryPostProcessor 两种类型的处理,上半部分主要处理 BeanDefinitionRegistryPostProcessor,下半部分则是处理 BeanFactoryPostProcessor。

BeanDefinitionRegistryPostProcessor 则是对 BeanFactoryPostProcessor 的扩展,而 BeanDefinitionRegistryPostProcessor 因为比 BeanFactoryPostProcessor 类型的 bean 先处理,因此 BeanDefinitionRegistryPostProcessor 的优先级更高。

BeanDefinitionRegistryPostProcessor 有一个实现的子类 ConfigurationClassPostProcessor,主要是用来处理使用 @Configuration 标记的 Bean,而 BeanFactoryPostProcessor 则是处理在 xml 文件中配置的 Bean。

调用 BeanFactoryPostProcessor

主要代码:AbstractApplicationContext#invokeBeanFactoryPostProcessors()

protected void invokeBeanFactoryPostProcessors(
	ConfigurableListableBeanFactory beanFactory
) {
    // 处理 BeanFactoryPostProcessors
    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()));  
    }  
}
查找并调用 BeanFactoryPostProcessor

主要代码:PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()

public static void invokeBeanFactoryPostProcessors(
	ConfigurableListableBeanFactory beanFactory, 
	List<BeanFactoryPostProcessor> beanFactoryPostProcessors
) {  

    Set<String> processedBeans = new HashSet<>();  

    // 处理 BeanDefinitionRegistry 类型的 beanFactory
    if (beanFactory instanceof BeanDefinitionRegistry) {  
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;  
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();  
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();  

        // 已经注册过的 BeanFactoryPostProcessor
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
        	// 常规处理
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {  
                BeanDefinitionRegistryPostProcessor registryProcessor = (BeanDefinitionRegistryPostProcessor) postProcessor;  
                registryProcessor.postProcessBeanDefinitionRegistry(registry);  
                registryProcessors.add(registryProcessor);  
            }  
	        else {
	            // 常规处理
	            regularPostProcessors.add(postProcessor);  
	        }  
	    }
    
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();  
  
        // 获取注册过的 BeanDefinitionRegistryPostProcessor 类型的 bean
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); 
        // 同时匹配实现 PriorityOrdered 接口的 bean
        for (String ppName : postProcessorNames) {  
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {  
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));  
				processedBeans.add(ppName);  
	        }  
	    }
        // 进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);  
        registryProcessors.addAll(currentRegistryProcessors);  
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  
        currentRegistryProcessors.clear();  
  
        // 这边和上面的步骤差不多,只是筛选的对象从上面的 PriorityOrdered 改为了 Ordered 对象
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);  
        for (String ppName : postProcessorNames) {  
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {  
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));  
                processedBeans.add(ppName);  
            }  
        }
        // 进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);  
        registryProcessors.addAll(currentRegistryProcessors);  
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  
        currentRegistryProcessors.clear();  
  
        // 这边还会在重复一次之前的操作,直到没有遗漏的
        boolean reiterate = true;  
        while (reiterate) {  
            reiterate = false;  
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);  
            for (String ppName : postProcessorNames) {  
                if (!processedBeans.contains(ppName)) {  
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));  
                    processedBeans.add(ppName);  
                    reiterate = true;  
                }  
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);  
            registryProcessors.addAll(currentRegistryProcessors);  
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);  
            currentRegistryProcessors.clear();  
        }  
  
        // 加载注册过的 Bean
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);  
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);  
    }
    else {  
        // 加载普通的 Bean
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);  
    }  
  
    // 获取 BeanFactoryPostProcessor 类型的 Bean
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);  

    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();  
    List<String> orderedPostProcessorNames = new ArrayList<>();  
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();  
    for (String ppName : postProcessorNames) {  
        if (processedBeans.contains(ppName)) {  
            // 跳过之前已经处理过的 Bean
        }  
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // PriorityOrdered 排过序的
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));  
        }  
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // Ordered 排过序的
            orderedPostProcessorNames.add(ppName);  
        }  
        else {
            // 无序的
            nonOrderedPostProcessorNames.add(ppName);  
        }  
    }  
  
    // 先调用经过 PriorityOrdered 排序的 
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);  
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);  
  
    // 对经过 Ordered 排序的Bean
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());  
    for (String postProcessorName : orderedPostProcessorNames) {  
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));  
    }  
    sortPostProcessors(orderedPostProcessors, beanFactory);  
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);  
  
    // 调用普通的 BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());  
    for (String postProcessorName : nonOrderedPostProcessorNames) {  
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));  
    }  
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);  
  
    // 清空缓存
    beanFactory.clearMetadataCache();  
}

在之前两种配置方式中,涉及到 PropertySourcesPlaceholderConfigurer 和 PropertyPlaceholderConfigurer,通过对两个类的继承图分析,可以发现其中都涉及到了抽象类 PlaceholderConfigurerSupport,其中抽象类实现了接口 BeanFactoryPostProcessor 中的 postProcessBeanFactory() 方法,在后续的 invokeBeanFactoryPostProcessors() 方法中会进行执行。
![[Pasted image 20220824121617.png]]

而 PlaceholderConfigurerSupport 的父级抽象类 PropertyResourceConfigurer 则默认实现了 postProcessBeanFactory() 方法。其中涉及到三个方法 mergeProperties()convertProperties()processProperties()。这三个方法分别是调用配置,转换值的类型以及对值进行处理然后告知 BeanFactory。

@Override  
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {  
   try {
      // 获取配置
      Properties mergedProps = mergeProperties();  
  
      // 转换值的类型,如果有需要可以使用子类重写
      convertProperties(mergedProps);  
  
      // 子类执行调用,对配置的值进行处理
      processProperties(beanFactory, mergedProps);  
   }  
   catch (IOException ex) {  
      throw new BeanInitializationException("Could not load properties", ex);  
   }  
}

(二) 注册 BeanPostProcessors

注册 BeanPostProcessor 的方法会和上面的调用 BeanFactoryPostProcessors 过程类似,只不过换了 BeanPostProcessor 类型进行处理。

这边只是暂时将 BeanPostProcessor 类型的 Bean 添加到 AbstractBeanFactory 中的列表中,也就是进行 Bean 的注册,等待 bean 的实例化的时候进行调用。

public static void registerBeanPostProcessors(
	ConfigurableListableBeanFactory beanFactory, 
	AbstractApplicationContext applicationContext
) {  

    // 获取 BeanPostProcessor 类型的 Bean
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);    
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;  
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));  
  
    // 区分普通的、PriorityOrdered 和 Ordered 类型的 BeanPostProcessor
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();  
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();  
    List<String> orderedPostProcessorNames = new ArrayList<>();  
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();  
    for (String ppName : postProcessorNames) {  
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {  
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);  
		    priorityOrderedPostProcessors.add(pp);
	        if (pp instanceof MergedBeanDefinitionPostProcessor) {  
	            internalPostProcessors.add(pp);  
	        }
        }
	    else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {  
	        orderedPostProcessorNames.add(ppName);  
	    }
	    else {  
	        nonOrderedPostProcessorNames.add(ppName);  
	    }
    }  
  
    // 进行排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 调用 ConfigurableListableBeanFactory#addBeanPostProcessor
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);  
  
    // 处理 Ordered 类型的 Bean
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());  
	for (String ppName : orderedPostProcessorNames) {  
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);  
        orderedPostProcessors.add(pp);  
        if (pp instanceof MergedBeanDefinitionPostProcessor) {  
            internalPostProcessors.add(pp);  
        }  
    }  
    sortPostProcessors(orderedPostProcessors, beanFactory);  
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);  
  
    // 处理普通类型的 Bean
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());  
    for (String ppName : nonOrderedPostProcessorNames) {  
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);  
        nonOrderedPostProcessors.add(pp);  
        if (pp instanceof MergedBeanDefinitionPostProcessor) {  
            internalPostProcessors.add(pp);  
        }  
    }  
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);  
  
    // 对 MergedBeanDefinitionPostProcessor 类型的 Bean 进行处理
    sortPostProcessors(internalPostProcessors, beanFactory);  
    registerBeanPostProcessors(beanFactory, internalPostProcessors);  
    
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瞎叨叨的一天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值