Spring源码解析-BeanFactoryPostProcessor

BeanFactoryPostProcessor的定义和作用

在这篇Spring源码解析-BeanPostProcessor 文章了解了bean初始化后对其实例的修改,本文则探讨另外一个接口,是bean初始化之前供你修改bean配置数据元(即bean definition)的回调接口。这也是BeanPostProcessor和BeanFactoryPostProcessor的最主要的区别。Application Contexts 能够自动的检测到BeanFactoryPostProcessor beans并被应用于其他bean被实例之前去修改属性。这也很方便我们能够在初始化bean之前对bean做些特殊处理。在Spring里也提供了一组这样的实现类,如:PropertyPlaceholderConfigurerPropertyOverrideConfigurer 等都是这个接口的实现类,我们也可以自己去实现这个接口,并实现自己的业务逻辑。

BeanFactoryPostProcessor方法

该接口很简单,只有一个方法:

public interface BeanFactoryPostProcessor {

	/**
	 * 实现该方法,去修改bean definition
	 */
	void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

该接口还有个扩展接口,就是BeanDefinitionRegistryPostProcessor,实现这个接口之类,会在BeanFactoryPostProcessor之前就被执行,BeanDefinitionRegistryPostProcessor可以注册更多的bean definition在BeanFactoryPostProcessor调用之前。该接口也只有一个方法:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * 运行增加更多的bean定义
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

在spring中,我们会用注解的方式代替XML方式来注册bean,我们会在类上面注解Configuration这个注解来注册bean,而这些bean就是通过BeanDefinitionRegistryPostProcessor这个接口来实现注册bean的定义的。具体下面来看下具体的实现到底是怎么做的。

BeanFactoryPostProcessor的实现

PropertyPlaceholderConfigurer的作用就是在实例化bean之前,把bean定义里面的所有的通配符字段替换成配置文件里面配置的值,举个最常见的例子,配置数据源,我们都会用通配符去获取配置文件,如下配置:

<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
		<property name="driverClassName" value="${database.driverClassName}" />
		<property name="url" value="${database.url}" />
		<property name="username" value="${database.username}" />
		<property name="password" value="${database.password}" />
</bean>		

spring创建这个bean definition的时候并没有把真正的配置文件里面的值set到属性里面去,这时候就需要BeanFactoryPostProcessor的实现类来去在实例化这个数据源的之前进行通配符的替换,这也就是PropertyPlaceholderConfigurer的工作了,具体怎么替换不展开讲了,自行脑补,具体的实现如下:

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		if (this.propertySources == null) {
			this.propertySources = new MutablePropertySources();
			if (this.environment != null) {
				this.propertySources.addLast(
					new PropertySource<Environment>(ENVIRONMENT_PROPERTIES_PROPERTY_SOURCE_NAME, this.environment) {
						@Override
						public String getProperty(String key) {
							return this.source.getProperty(key);
						}
					}
				);
			}
			try {
				PropertySource<?> localPropertySource =
						new PropertiesPropertySource(LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME, mergeProperties());
				if (this.localOverride) {
					this.propertySources.addFirst(localPropertySource);
				}
				else {
					this.propertySources.addLast(localPropertySource);
				}
			}
			catch (IOException ex) {
				throw new BeanInitializationException("Could not load properties", ex);
			}
		}

		processProperties(beanFactory, new PropertySourcesPropertyResolver(this.propertySources));
		this.appliedPropertySources = this.propertySources;
	}

该实现业务,就是替换掉${}这些通配符在bean definition里面。就是在初始化之前去修改bean定义。假如我们要增加更多的bean definition,我们可以用另外一个接口BeanDefinitionRegistryPostProcessor,在Spring中也有这样的实现,如ConfigurationClassPostProcessor,这个类的作用就是自动检测到@Configuration注解的类并解析里面的@Bean方法以及其他的如@Import之类的等等都是这个类来做的,解析是将为这些bean创建bean definition,并注册到容器里面去,就是我们上面说到的,他的作用就是为了注册更多的bean用的。具体代码如下:

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		this.registriesPostProcessed.add(registryId);
		//处理解析并注册bean定义
		processConfigBeanDefinitions(registry);
	}

具体也不张开将,我们主要明白这两个接口是来干嘛用的就行了。如果有类似的需求,我们可以用这两个接口来扩展我们的业务。

总结

通过对BeanFactoryPostProcessor和BeanPostProcessor对比,两者的区别以及作用,都能够很好的帮助我们在后续的开发工作中更好的写出优雅的代码。Spring提供了很多这种接口方便我们去处理某类业务,像BeanFactoryPostProcessor就是去修改bean definition而BeanPostProcessor是去修改实例化后的对象,这些都是很好的后置处理器。

转载于:https://my.oschina.net/wang5v/blog/3019780

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值