Spring BeanFactoryPostProcessor 接口
[[Spring IOC 源码学习总笔记]]
BeanFactoryPostProcessor是 Spring 框架提供的一个扩展点接口,它允许开发者在 Spring 在BeanFactory 加载了所有bean定义,但尚未实例化任何bean 之后,对底层的 BeanDefinition 和 BeanFactory 进行扩展定制, 包括修改已注册的bean定义 添加新的bean定义等等。
BeanFactoryPostProcessor的主要作用包括:
- 修改已注册的Bean定义: 可以通过
BeanFactoryPostProcessor来修改已注册的bean的配置信息,例如修改属性值、添加新的属性等。 - 添加新的Bean定义: 可以向容器中添加新的bean定义,这样在实例化bean时,新定义的bean也会被纳入管理。
- 对Bean定义进行后处理: 可以在容器加载了bean的定义后对这些定义进行后处理,以满足特定的需求。
BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor 的源码
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
/**
* Factory hook that allows for custom modification of an application context's
* bean definitions, adapting the bean property values of the context's underlying
* bean factory.
*
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context. See
* {@link PropertyResourceConfigurer} and its concrete implementations for
* out-of-the-box solutions that address such configuration needs.
*
* <p>A {@code BeanFactoryPostProcessor} may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* <h3>Registration</h3>
* <p>An {@code ApplicationContext} auto-detects {@code BeanFactoryPostProcessor}
* beans in its bean definitions and applies them before any other beans get created.
* A {@code BeanFactoryPostProcessor} may also be registered programmatically
* with a {@code ConfigurableApplicationContext}.
*
* <h3>Ordering</h3>
* <p>{@code BeanFactoryPostProcessor} beans that are autodetected in an
* {@code ApplicationContext} will be ordered according to
* {@link org.springframework.core.PriorityOrdered} and
* {@link org.springframework.core.Ordered} semantics. In contrast,
* {@code BeanFactoryPostProcessor} beans that are registered programmatically
* with a {@code ConfigurableApplicationContext} will be applied in the order of
* registration; any ordering semantics expressed through implementing the
* {@code PriorityOrdered} or {@code Ordered} interface will be ignored for
* programmatically registered post-processors. Furthermore, the
* {@link org.springframework.core.annotation.Order @Order} annotation is not
* taken into account for {@code BeanFactoryPostProcessor} beans.
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* 在加载了所有bean定义,但尚未实例化任何bean。(可以对底层的 BeanDefinition 和 BeanFactory 进行扩展定制)
*
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
相关源码
org.springframework.context.support.AbstractApplicationContext#refresh 部分源码
@Override
public void refresh() throws BeansException, IllegalStateException {
// 容器刷新, 执行时, 需要锁住
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
/**
* 一, (ApplicationContex)预准备工作;
*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/**
* 二, 获取一个新的 BeanFactory;
*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
/**
* 三,(BeanFactory)预准备工作;
*/
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
/**
* 四, beanFactory 已经准备好了, 给子类(Context)预留一个扩展点; (这里是空实现)
*/
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
/**
* 五, 调用 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor;
* 还要注意一点 BeanDefinitionRegistryPostProcessor 是继承自 BeanFactoryPostProcessor的
*
* 总的来说, 调用的优先级是
* 1. 调用接口的优先级:
* 1. 优先调用(子类) BeanDefinitionRegistryPostProcessor
* 2. 再调用(父类) BeanFactoryPostProcessor
* 2. 调用添加的方式的优先级:
* 1. 优先调用外部入参, 即直接通过{@link AbstractApplicationContext#addBeanFactoryPostProcessor(org.springframework.beans.factory.config.BeanFactoryPostProcessor)} 代码添加的
* 2. 再调用容器中实现 BeanFactoryPostProcessor 或者 BeanDefinitionRegistryPostProcessor 的 Bean
* 见: {@link org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)}
*
* 比如:
* {@link org.springframework.context.support.PropertySourcesPlaceholderConfigurer} 处理 SPEL 表达式的
*/
invokeBeanFactoryPostProcessors(beanFactory);
....
BeanDefinitionRegistryPostProcessor 接口
BeanDefinitionRegistryPostProcessor(BDRPP) 接口继承自BeanFactoryPostProcessor(BFPP) 它会优先于BFPP调用, 目的是可以在BFPP之前 注册/修改 BeanDefinition 到 BeanFactory中
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
package org.springframework.beans.factory.support;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* 对标准 {@link BeanFactoryPostProcessor} SPI的扩展,允许在常规 BeanFactoryPostProcessor检测开始之前注册更多的bean定义。
* 特别是,BeanDefinitionRegistryPostProcessor 可以注册进一步的bean定义,这些bean定义又定义了 BeanFactoryPostProcessor 实例。
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
/**
* Empty implementation of {@link BeanFactoryPostProcessor#postProcessBeanFactory}
* since custom {@code BeanDefinitionRegistryPostProcessor} implementations will
* typically only provide a {@link #postProcessBeanDefinitionRegistry} method.
* @since 6.1
*/
@Override
default void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
Srping 对于注解的支持实现
一个例子是在 Spring 中 对于注解的支持就是通过 BeanDefinitionRegistryPostProcessor的扩展实现的, 见关系图

注意: 关于 Spring IOC 支持注解最原始的入口点 并不在这.
本文只讨论 Spring 是如何通过 BeanDefinitionRegistryPostProcessor 扩展实现对注解的支持
org.springframework.context.annotation.ConfigurationClassPostProcessor 部分源码
/**
* 主要负责解析注解的关键类, 注意它实现的其中一个接口: BeanDefinitionRegistryPostProcessor
*
* {@link BeanFactoryPostProcessor} used for bootstrapping processing of
* {@link Configuration @Configuration} classes.
* <p>Registered by default when using {@code <context:annotation-config/>} or
* {@code <context:component-scan/>}. Otherwise, may be declared manually as
* with any other {@link BeanFactoryPostProcessor}.
*
* <p>This post processor is priority-ordered as it is important that any
* {@link Bean @Bean} methods declared in {@code @Configuration} classes have
* their corresponding bean definitions registered before any other
* {@code BeanFactoryPostProcessor} executes.
*
* @author Chris Beams
* @author Juergen Hoeller
* @author Phillip Webb
* @author Sam Brannen
* @since 3.0
*/
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
BeanRegistrationAotProcessor, BeanFactoryInitializationAotProcessor, PriorityOrdered,
ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
public ConfigurationClassPostProcessor(){
System.out.println("ConfigurationClassPostProcessor 构造");
}
....
/**
* Build and validate a configuration model based on the registry of
* {@link Configuration} classes.
*/
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
/**
* 存所有视为 Candidate 的 BeanDefinition
*/
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//拿到所有的已注册的 Bean Name
String[] candidateNames = registry.getBeanDefinitionNames();
// 遍历, 筛选视为 Candidate 的 beanDefinition, 把它们添加到 configCandidates 中
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
/**
* BeanDefinition 如果包含 configurationClass 属性, 则表示该 beanDefinition 已经被处理过了
*/
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
/**
* 如果是该 (bean)beanDefinition
* 1. 添加了 @Configuration 会被视作是 Candidate 放入 configCandidates
* 2. 如果添加了 @Component, @ComponentScan @Import ,@ImportResource 或者 有方法是添加了 @Bean 注解的, 也会被视作是 Candidate 放入 configCandidates
* 并且给它设置属性 configurationClass 值为 'lite' 区分一下
*
* <!> 所以能被 Spring 识别为bean 添加到容器中的注解, 就是以上的2种情况.
*/
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
// 如果没有任何 Candidate , 返回
if (configCandidates.isEmpty()) {
return;
}
// 排序 即: @Order
// Sort by previously determined @Order value, if applicable
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
/**
* 这一块是对 bean的 自定义命名生成 策略的处理
*/
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry _sbr) {
sbr = _sbr;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);//这个是默认的 名称生成器
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
// 环境对象
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
/**
* ConfigurationClassParser: 解析注解的关键解析对象
* 又开始倒手了.
*/
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
// 用 set 方便去重 集合运算吧
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
// 已经解析处理过的
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
/**
* <!> 重点, 用 ConfigurationClassParser 去解析
* 最终得到的是 Set<ConfigurationClass> !
*/
parser.parse(candidates);
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
// 移出 已经解析处理过的
configClasses.removeAll(alreadyParsed);
/**
* <!> 重点, 解析得到 Set<ConfigurationClass> 再用 ConfigurationClassBeanDefinitionReader 去加载 BeanDefinition
*/
// Read the model and create bean definitions based on its content
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = Set.of(candidateNames);
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
// Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
this.propertySourceDescriptors = parser.getPropertySourceDescriptors();
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
cachingMetadataReaderFactory.clearCache();
}
}
.....

浙公网安备 33010602011771号