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

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

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

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

205318_i9jO_2882456.jpeg

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对属性的封装类图。

213220_JCj8_2882456.png

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值