加载完BeanDiFinition后,可以对BeanDiFinition做某些操作,比如修改BeanDiFinition以及新增BeanDiFinition。Spring提供了beanfactoryPostProcessor接口对BeanDiFinition进行扩展。
AbstractApplicationContext.class
invokebeanfactoryPostProcessors(beanfactory); // 执行beanfactoryPostProcessor
protected void invokebeanfactoryPostProcessors(ConfigurableListablebeanfactory beanfactory) {
PostProcessorRegistrationDelegate.invokebeanfactoryPostProcessors(beanfactory, getbeanfactoryPostProcessors());
// Detect a LoadTimeweaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClasspostProcessor)
if (!NativeDetector.inNativeImage() && beanfactory.getTempClassLoader() == null && beanfactory.containsBean(LOAD_TIME_weaveR_BEAN_NAME)) {
beanfactory.addBeanPostProcessor(new LoadTimeweaverAwareProcessor(beanfactory));
beanfactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanfactory.getBeanClassLoader()));
}
}
Spring还提供了beanfactoryPostProcessor的子接口BeanDeFinitionRegistryPostProcessor用于新增BeanDeFinition。
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;
}
PostProcessorRegistrationDelegate.java
public static void invokebeanfactoryPostProcessors(
ConfigurableListablebeanfactory beanfactory, List<beanfactoryPostProcessor> beanfactoryPostProcessors) {
// WARNING: Although it may appear that the body of this method can be easily
// refactored to avoid the use of multiple loops and multiple lists, the use
// of multiple lists and multiple passes over the names of processors is
// intentional. We must ensure that we honor the contracts for PriorityOrdered
// and Ordered processors. Specifically, we must NOT cause processors to be
// instantiated (via getBean() invocations) or registered in the ApplicationContext
// in the wrong order.
//
// Before submitting a pull request (PR) to change this method, please review the
// list of all declined PRs involving changes to PostProcessorRegistrationDelegate
// to ensure that your proposal does not result in a breaking change:
// https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22
// Invoke BeanDeFinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanfactory instanceof BeanDeFinitionRegistry) {
BeanDeFinitionRegistry registry = (BeanDeFinitionRegistry) beanfactory;
List<beanfactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDeFinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (beanfactoryPostProcessor postProcessor : beanfactoryPostProcessors) {
if (postProcessor instanceof BeanDeFinitionRegistryPostProcessor) {
BeanDeFinitionRegistryPostProcessor registryProcessor =
(BeanDeFinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDeFinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize factorybeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDeFinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDeFinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDeFinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanfactory.getBeanNamesForType(BeanDeFinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanfactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanfactory.getBean(ppName, BeanDeFinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanfactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDeFinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanfactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Next, invoke the BeanDeFinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanfactory.getBeanNamesForType(BeanDeFinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanfactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanfactory.getBean(ppName, BeanDeFinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanfactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDeFinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanfactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDeFinitionRegistryPostProcessors until no further ones appear.
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, beanfactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessbeanfactory callback of all processors handled so far.
invokebeanfactoryPostProcessors(registryProcessors, beanfactory);
invokebeanfactoryPostProcessors(regularPostProcessors, beanfactory);
}
else {
// Invoke factory processors registered with the context instance.
invokebeanfactoryPostProcessors(beanfactoryPostProcessors, beanfactory);
}
// Do not initialize factorybeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanfactory.getBeanNamesForType(beanfactoryPostProcessor.class, true, false);
// 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);
}
}
// First, invoke the beanfactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanfactory);
invokebeanfactoryPostProcessors(priorityOrderedPostProcessors, beanfactory);
// Next, invoke the beanfactoryPostProcessors that implement Ordered.
List<beanfactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanfactory.getBean(postProcessorName, beanfactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanfactory);
invokebeanfactoryPostProcessors(orderedPostProcessors, beanfactory);
// Finally, invoke all other beanfactoryPostProcessors.
List<beanfactoryPostProcessor> 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();
}
invokebeanfactoryPostProcessors方法执行流程如下:
-
遍历参数beanfactoryPostProcessors,判断是否是BeanDeFinitionRegistryPostProcessor,若是则执行BeanDeFinitionRegistryPostProcessor的postProcessBeanDeFinitionRegistry方法,并加入registryProcessors集合,否则加入regularPostProcessors集合
-
从beanfactory中获取BeanDeFinitionRegistryPostProcessor,并按照PriorityOrdered,Ordered和没有实现Ordered的优先级依次执行BeanDeFinitionRegistryPostProcessor的postProcessBeanDeFinitionRegistry方法,并加入registryProcessors集合,直到beanfactory中没有未执行的BeanDeFinitionRegistryPostProcessor的Bean。
-
执行BeanDeFinitionRegistryPostProcessor的postProcessbeanfactory方法,及执行registryProcessors集合里的BeanDeFinitionRegistryPostProcessor对象的postProcessbeanfactory方法。
-
执行参数beanfactoryPostProcessors里面类型beanfactoryPostProcessor的postProcessbeanfactory方法。
-
执行beanfactory里的beanfactoryPostProcessor的postProcessbeanfactory方法。按照PriorityOrdered,Ordered,没有实现Ordered的次序依次执行
因为执行BeanDeFinitionRegistryPostProcessor的postProcessBeanDeFinitionRegistry方法可能会新增BeanDeFinition,所以要用where循环判断beanfactory中没有未执行的BeanDeFinitionRegistryPostProcessor实例。
BeanDeFinitionRegistryPostProcessor例子:
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
public class UserBeanDeFinitionRegistryPostProcessor implements BeanDeFinitionRegistryPostProcessor {
@Override
public void postProcessbeanfactory(ConfigurableListablebeanfactory beanfactory) throws BeansException {
}
@Override
public void postProcessBeanDeFinitionRegistry(BeanDeFinitionRegistry registry) throws BeansException {
BeanDeFinitionBuilder builder = BeanDeFinitionBuilder.rootBeanDeFinition(User.class);
builder.addPropertyValue("id",1);
builder.addPropertyValue("name","王五");
registry.registerBeanDeFinition("user",builder.getBeanDeFinition());
}
}
app.xml
<bean class="xml.UserBeanDeFinitionRegistryPostProcessor"/>
测试:
ApplicationContext applicationContext = new ClasspathXmlApplicationContext("classpath:app.xml");
User bean = applicationContext.getBean(User.class);
System.out.println(bean);
结果:
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。