BeanFactoryPostProcessor是Spring中一个相当重要的扩展点,扩展点就是能让我们在Spring容器以及Bean生命周期的各个阶段中可以进行修改扩展。
BeanFactoryPostProcessor, 翻译过来大致是Bean的工厂处理器,顾名思义,可以理解为它对Bean工厂中Bean定义(BeanDefintion)进行修改, 它的执行时机:BeanFactory标准初始化之后,所有的Bean定义已经被加载,但标准Bean的实例还没被创建(不包括BeanFactoryPostProcessor类型)。该方法通常用于修改bean的定义,Bean的属性值等,甚至可以在此快速初始化Bean。
而另外一个相关的扩展接口的BeanDefinitionRegistryPostProcessor,继承自BeanFactoryPostProcessor,所有的Bean定义即将被加载,但Bean的实例还没被创建时,也就是说,BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法执行时机先于BeanFactoryPostProcessor的postProcessBeanFactory方法。
区别于一个很类似的扩展接口BeanPostProcessor, 它的执行时机实在Bean初始化前后,添加一些自己想要的逻辑。
小结一下,上面关联的扩展接口执行顺序如下:1.BeanDefinitionRegistryPostProcessor,2.BeanFactoryPostProcessor,3.BeanPostProcessor。而BeanFactoryPostProcessor主要是在标准的BeanDefinition已经准备完毕,可以去修改已有的BeanDefinition的相关属性等。
@Data
@Component
public class Student {
@Value("${user.username:alvin}")
private String username;
@Value("${user.age:12}")
private int age;
}
@Component
@Slf4j
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
log.info("******************** TestBeanFactoryPostProcessor#postProcessBeanFactory ****************");
log.info("******************** bean的数量:[{}] ****************", beanFactory.getBeanDefinitionCount());
// 修改bean definition属性信息
BeanDefinition userBeanDef = beanFactory.getBeanDefinition("student");
userBeanDef.getPropertyValues().add("username", "cxw");
// 快速初始化Bean
User user = (User)beanFactory.getBean("student");
log.info("student name: [{}]", user.getUsername());
}
}
bean的属性被成功被修改了。
/**
* 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.
*
* 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.
*
*
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.
*
*
Registration
* 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}.
*
*
Ordering
* {@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.
* @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;
}
接口的注释很清楚的说明了它的作用和细节,大致有下面几点:
其中核心逻辑是PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法,该方法的前面部分逻辑主要是处理BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,也就是想BeanDefinition注册中中心添加新的BeanDefinition。
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {
.......... 该部分是处理BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry相关逻辑,跳过, 可以看BeanDefinitionRegistryPostProcessor的解析
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// 获取所有实现了BeanFactoryPostProcessor接口的bean name列表,前提是在BeanFactory的BeanDefinitions列表中包含对应的bean定义信息。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 存放实现了PriorityOrdered接口的processor
List priorityOrderedPostProcessors = new ArrayList<>();
// 存放实现了Ordered接口的processor
List orderedPostProcessorNames = new ArrayList<>();
// 存放没有实现排序的processor
List nonOrderedPostProcessorNames = new ArrayList<>();
// 遍历前面全量的bean name,将他们归类,放到上面的容器中
for (String ppName : postProcessorNames) {
// 如果在第一阶段已经被调用过,就不调用,第一阶段主要是BeanDefinitionRegistryPostProcessor,它继承了BeanFactoryPostProcessor,它会在第一阶段调用。
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);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// 首先执行实现了PriorityOrdered接口的processor,对它们进行排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 真实执行processor中的逻辑。
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// 其次执行实现了Ordered接口的processor,对它们进行排序后执行processor中的逻辑。
List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 最后执行,没有顺序要求的processor
List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
//调用processors中的postProcessBeanFactory方法
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
StartupStep postProcessBeanFactory = beanFactory.getApplicationStartup().start("spring.context.bean-factory.post-process")
.tag("postProcessor", postProcessor::toString);
postProcessor.postProcessBeanFactory(beanFactory);
postProcessBeanFactory.end();
}
}
整个执行流程的源码还是比较清晰并且简单的。重点提下下面两个点:
看源码得知,String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);获取所有实现了BeanFactoryPostProcessor的Bean Name, 前提所有的Bean都要被注册到BeanDefinitionRegistry, 通过添加@Component, @Service等注解,可以将对应的Bean定义信息注册到BeanFactory中,方便后面实例化Bean。 那么它是在什么地方注册的呢?可以看下ConfigurationClassPostProcessor类,它实现了BeanDefinitionRegistryPostProcessor,会扫描所有@Component, @Service等注解,将对应的Bean Definition注册到BeanFactory中。
我们可以通过实现PriorityOrdered, Ordered接口,控制BeanFactoryProcessor的执行顺序,, 优先执行实现了PriorityOrdered接口,其次是Ordered,最后是没有实现任何排序接口的processor。
Spring内置了一个比较重要的BeanFactoryPostProcessor是PlaceholderConfigurerSupport, 实现从配置文件中获取属性。
作者:JAVA旭阳
链接:https://juejin.cn/post/7107561134860959757
“做程序员,圈子和学习最重要”因为有有了圈子可以让你少走弯路,扩宽人脉,扩展思路,学习他人的一些经验及学习方法!同时在这分享一下是一直以来整理的Java后端进阶笔记文档和学习资料免费分享给大家!需要资料的朋友私信我扣【888】
页面更新:2024-04-19
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号