Spring源码-如何修改BeanDefinition的属性

Spring源码-如何修改BeanDefinition的属性

在实际开发中,我们有的时候并不是把所有的核心配置文件都存放到本地配置文件xxx..properties中的,而是通过远程去加载对应的配置文件信息。有的公司还有自己的独立配置中心系统,主要用来管理所有配置信息的。基于这个需求,其实我们利用Spring的后置处理器BeanFactoryPostProcessor扩展点是可以解决的,在Spring容器加载的时候就动态的远程获取到配置信息来更改配置。下面我们就一块来分析一下Spring给开发者预留的这个扩展点吧!

1. 首先,我们看一下本次的最为重要的二个类(BeanFactoryPostProcessor,BeanDefinitionRegistryPostProcessor),这二个类都能用于扩展。还有就是多个后置处理的调用顺序也是可以调整的,这个时候涉及到PriorityOrdered和Ordered,也比较重要。

2. 紧接着我们写几个测试类来测试一下他们的调用顺序。

applicationContent.xml中加入如下bean配置:

<bean class="cn.edu.his.pay.postprocess.My1"/>
<bean class="cn.edu.his.pay.postprocess.My2"/>
<bean class="cn.edu.his.pay.postprocess.My3"/>
<bean class="cn.edu.his.pay.postprocess.My4"/>
<bean class="cn.edu.his.pay.postprocess.My5"/>
<bean class="cn.edu.his.pay.postprocess.My6"/>
<bean class="cn.edu.his.pay.postprocess.My9"/>
 
<bean class="cn.edu.his.pay.postprocess.Student" id="student">
    <property name="username" value="qrmc"></property>
    <property name="password" value="123456"></property>
</bean>
My1.java

package cn.edu.his.pay.postprocess;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 
public class My1 implements BeanFactoryPostProcessor {
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
        System.out.println("BeanFactoryPostProcessor my1");
 
        BeanDefinition bd = arg0.getBeanDefinition("student");
 
        MutablePropertyValues mpv = bd.getPropertyValues();
 
        mpv.addPropertyValue("password", "fhdksafhldsafjl");
    }
 
}
My2.java

package cn.edu.his.pay.postprocess;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
 
public class My2 implements BeanDefinitionRegistryPostProcessor {
 
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
        // TODO Auto-generated method stub
    }
 
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor my2");
 
        BeanDefinition bd = arg0.getBeanDefinition("student");
        MutablePropertyValues mpv = bd.getPropertyValues();
 
        mpv.addPropertyValue("username", "qrmc-vip");
    }
 
}
My3.java

package cn.edu.his.pay.postprocess;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.PriorityOrdered;
 
public class My3 implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
        // TODO Auto-generated method stub
    }
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor PriorityOrdered my3");
    }
 
    @Override
    public int getOrder() {
        // TODO Auto-generated method stub
        return 0;
    }
 
}
My4.java

package cn.edu.his.pay.postprocess;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.PriorityOrdered;
 
public class My4 implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
        // TODO Auto-generated method stub
    }
 
    @Override
    public int getOrder() {
        // TODO Auto-generated method stub
        return 1;
    }
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor PriorityOrdered my4");
 
    }
 
}
My5.java

package cn.edu.his.pay.postprocess;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.Ordered;
 
public class My5 implements BeanDefinitionRegistryPostProcessor, Ordered {
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
            throws BeansException {
        // TODO Auto-generated method stub
    }
 
    @Override
    public int getOrder() {
        // TODO Auto-generated method stub
        return 0;
    }
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0)
            throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor Ordered my5");
 
        BeanDefinition bd = arg0.getBeanDefinition("student");
        MutablePropertyValues mpv = bd.getPropertyValues();
        
        mpv.addPropertyValue("school", "qiurimangcao"); //添加属性并复制
 
    }
 
}
My6.java

package cn.edu.his.pay.postprocess;
 
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.Ordered;
 
public class My6 implements BeanDefinitionRegistryPostProcessor, Ordered {
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0) throws BeansException {
        // TODO Auto-generated method stub
    }
 
    @Override
    public int getOrder() {
        // TODO Auto-generated method stub
        return 1;
    }
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry arg0) throws BeansException {
        System.out.println("BeanDefinitionRegistryPostProcessor Ordered my6");
    }
 
}
执行后结果如下:

BeanDefinitionRegistryPostProcessor PriorityOrdered my3
BeanDefinitionRegistryPostProcessor PriorityOrdered my4
BeanDefinitionRegistryPostProcessor Ordered my5
BeanDefinitionRegistryPostProcessor Ordered my6
BeanDefinitionRegistryPostProcessor my2
BeanFactoryPostProcessor my1
2. Spring 核心部分源码如下:

BeanDefinitionRegistryPostProcessor 相关。

// 首先,调用实现PriorityOrdered的BeanDefinitionRegistryPostProcessor。
String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
/* [
 * org.springframework.context.annotation.internalConfigurationAnnotationProcessor, 
 * org.mybatis.spring.mapper.MapperScannerConfigurer#0, 
 * org.mybatis.spring.mapper.MapperScannerConfigurer#1, 
 * cn.edu.his.pay.postprocess.My2#0, 
 * cn.edu.his.pay.postprocess.My3#0, 
 * cn.edu.his.pay.postprocess.My4#0, 
 * cn.edu.his.pay.postprocess.My5#0, 
 * cn.edu.his.pay.postprocess.My6#0
 * ]
 * */
for (String ppName : postProcessorNames) {
    if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { //是否实现了PriorityOrdered接口
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 首先调用实现了PriorityOrdered接口的
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear(); //清空map
 
// 接下来,调用实现Ordered的BeanDefinitionRegistryPostProcessors。
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
    if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { // 这里是实现orderd的调用
        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
        processedBeans.add(ppName);
    }
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 去调用实现Ordered接口的
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
 
// 最后,调用所有其他的BeanDefinitionRegistryPostProcessor,直到没有其他的出现。
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();
}
BeanFactoryPostProcessor 相关

String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
/**
 * [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, 
 * org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0, 
 * org.mybatis.spring.mapper.MapperScannerConfigurer#0, 
 * org.mybatis.spring.mapper.MapperScannerConfigurer#1, 
 * cn.edu.his.pay.postprocess.My1#0, cn.edu.his.pay.postprocess.My2#0, 
 * cn.edu.his.pay.postprocess.My3#0, cn.edu.his.pay.postprocess.My4#0, 
 * cn.edu.his.pay.postprocess.My5#0, 
 * cn.edu.his.pay.postprocess.My6#0, 
 * org.springframework.context.support.PropertySourcesPlaceholderConfigurer#1
 * ]
 */
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
    if (processedBeans.contains(ppName)) {
        // skip - already processed in first phase above
    }
    else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
        priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
    }
    else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
        orderedPostProcessorNames.add(ppName);
    }
    else {
        nonOrderedPostProcessorNames.add(ppName);
    }
}
 
// 首先,调用实现PriorityOrdered的BeanFactoryPostProcessor。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
 
// 接下来,调用实现Ordered的BeanFactoryPostProcessors。
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
    orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
 
// 最后,调用所有其他BeanFactoryPostProcessor。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
    nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
3. 结合源码和测试类测试结果可以得出:Spring是先对实现了BeanDefinitionRegistryPostProcessor 的类先进行调用,其次才是对实现了BeanFactoryPostProcessor 的类进行调用,除了这个因素外还有就是PriorityOrdered、Ordered和对应的getOrder的值。先调用的是PriorityOrdered的getOrder小的值,然后再调用PriorityOrdered大的值,紧接着再判断Ordered的getOrder小的值,然后再调用Ordered大的值。

4. 知道了多种后置处理器的调用顺序后,我们可以结合测试代码了解到如何去更改一个BeanDefinition的属性以及它们的类之间的关系,如下是BeanDefinition对属性的封装类图。

如上图,通过beanName可以从内存中取出对应的BeanDefinition,这样就可以直接拿到MutablePropertyValues,通过MutablePropertyValues的属性propertyValueList属性集合来修改或添加新值。
 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值