微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Spring源码-执行BeanFactoryPostProcessor

加载完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方法执行流程如下:

  1. 遍历参数beanfactoryPostProcessors,判断是否是BeanDeFinitionRegistryPostProcessor,若是则执行BeanDeFinitionRegistryPostProcessor的postProcessBeanDeFinitionRegistry方法,并加入registryProcessors集合,否则加入regularPostProcessors集合

  2. beanfactory获取BeanDeFinitionRegistryPostProcessor,并按照PriorityOrdered,Ordered和没有实现Ordered的优先级依次执行BeanDeFinitionRegistryPostProcessor的postProcessBeanDeFinitionRegistry方法,并加入registryProcessors集合,直到beanfactory中没有未执行的BeanDeFinitionRegistryPostProcessor的Bean。

  3. 执行BeanDeFinitionRegistryPostProcessor的postProcessbeanfactory方法,及执行registryProcessors集合里的BeanDeFinitionRegistryPostProcessor对象的postProcessbeanfactory方法

  4. 执行参数beanfactoryPostProcessors里面类型beanfactoryPostProcessor的postProcessbeanfactory方法

  5. 执行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] 举报,一经查实,本站将立刻删除。

相关推荐