Spring中那些BeanFactoryPostProcessors详解(二)

本文深入探讨Spring框架中BeanFactoryPostProcessor接口的实现类,包括PropertySourcesPlaceholderConfigurer、ConfigurationPropertiesBeanDefinitionValidator、EventListenerMethodProcessor及PreserveErrorControllerTargetClassPostProcessor的作用与实现细节。

关联博文:
Spring中那些BeanFactoryPostProcessors详解(一)
Spring中那些BeanFactoryPostProcessors详解(二)

本文是对Spring中refresh分析之invokeBeanFactoryPostProcessors方法详解的一个补充,我们详细说明一下那些BeanFactoryPostProcessor在invokeBeanFactoryPostProcessors方法中的作用。

【1】PropertySourcesPlaceholderConfigurer

其主要是用来解析BeanDefinition中的${...}占位符,使用propertySources中的值替代。

protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
		final ConfigurablePropertyResolver propertyResolver) throws BeansException {

	// ${
	propertyResolver.setPlaceholderPrefix(this.placeholderPrefix);
	// }
	propertyResolver.setPlaceholderSuffix(this.placeholderSuffix);
	// DEFAULT_VALUE_SEPARATOR = ":"
	propertyResolver.setValueSeparator(this.valueSeparator);

	StringValueResolver valueResolver = strVal -> {
		String resolved = (this.ignoreUnresolvablePlaceholders ?
				propertyResolver.resolvePlaceholders(strVal) :
				propertyResolver.resolveRequiredPlaceholders(strVal));
		if (this.trimValues) {
			resolved = resolved.trim();
		}
		return (resolved.equals(this.nullValue) ? null : resolved);
	};

	doProcessProperties(beanFactoryToProcess, valueResolver);
}

本文这里的propertySources如下所示:
在这里插入图片描述

【2】ConfigurationPropertiesBeanDefinitionValidator

BeanDefinition校验器,验证常规bean定义没有创建ConstructorBinding beans。

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
	for (String beanName : beanFactory.getBeanDefinitionNames()) {
		if (!(beanFactory.containsSingleton(beanName) || isValueObjectBeanDefinition(beanFactory, beanName))) {
			validate(beanFactory, beanName);
		}
	}
}

如果当前bean不是单例bean且对应BeanDefinition不是ConfigurationPropertiesValueObjectBeanDefinition,那么触发validate方法。

ConfigurationPropertiesValueObjectBeanDefinition用于注册在创建时绑定的@ConfigurationProperties值对象bean。

校验方法如下所示对BindMethod做了校验,如果是VALUE_OBJECT抛出异常

private void validate(ConfigurableListableBeanFactory beanFactory, String beanName) {
	try {
		Class<?> beanClass = beanFactory.getType(beanName, false);
		if (beanClass != null && BindMethod.forType(beanClass) == BindMethod.VALUE_OBJECT) {
			throw new BeanCreationException(beanName,
					"@EnableConfigurationProperties or @ConfigurationPropertiesScan must be used to add "
							+ "@ConstructorBinding type " + beanClass.getName());
		}
	}
	catch (CannotLoadBeanClassException ex) {
		// Ignore
	}

}

BindMethod有两种:JAVA_BEAN对应getter/setter绑定,VALUE_OBJECT对应构造器绑定。

【3】EventListenerMethodProcessor

这个玩意主要是对@EventListener方法做处理,其实现了SmartInitializingSingleton, ApplicationContextAware, BeanFactoryPostProcessor三个接口。

我们要对SmartInitializingSingleton有概念哦,当所有单例bean实例化后,会遍历触发SmartInitializingSingleton实例的afterSingletonsInstantiated方法。

postProcessBeanFactory方法如下所示,对EventListenerFactory进行排序然后赋予EventListenerMethodProcessor的成员List<EventListenerFactory> eventListenerFactories

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	this.beanFactory = beanFactory;

//获取容器中的EventListenerFactory
	Map<String, EventListenerFactory> beans = beanFactory.getBeansOfType(EventListenerFactory.class, false, false);
	List<EventListenerFactory> factories = new ArrayList<>(beans.values());
	//对其EventListenerFactory见排序
	AnnotationAwareOrderComparator.sort(factories);
	//排序后的factories赋予eventListenerFactories 
	this.eventListenerFactories = factories;
}

在这里插入图片描述

其afterSingletonsInstantiated方法则是会将当前bean中标注了@EventListener的方法封装为一个ApplicationListener(通常是ApplicationListenerMethodAdapter)。

【4】PreserveErrorControllerTargetClassPostProcessor

其是ErrorMvcAutoConfiguration的内部类确保在使用AOP时保留ErrorController MVC bean的目标类。

static class PreserveErrorControllerTargetClassPostProcessor implements BeanFactoryPostProcessor {

		@Override
		public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		//获取ErrorController
			String[] errorControllerBeans = beanFactory.getBeanNamesForType(ErrorController.class, false, false);
//遍历设置属性org.springframework.aop.framework.autoproxy.AutoProxyUtils.preserveTargetClass为true;
			for (String errorControllerBean : errorControllerBeans) {
				try {
					beanFactory.getBeanDefinition(errorControllerBean)
							.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
				}
				catch (Throwable ex) {
					// Ignore
				}
			}
		}
	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

流烟默

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

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

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

打赏作者

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

抵扣说明:

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

余额充值