spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

时间:2023-03-09 01:58:09
spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

更多文章点击--spring源码分析系列

主要分析内容:

一、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor简述与demo示例
二、BeanFactoryPostProcessor源码分析:注册时机和触发点

(源码基于spring 5.1.3.RELEASE分析)

一、BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor简述与demo示例

1、BeanFactoryPostProcessor是spring容器级别的拓展接口,是在BeanDefinition加载完成之后,未实例化之前.可以拓展接口,对定制化修改BeanDefinition.

 public interface BeanFactoryPostProcessor {

     void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

2、BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,是一种比较特殊的BeanFactoryPostProcessor。
BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法可实现自定义的bean注册定义。
通常spring注册bean使用静态方式, 如:xml、@Bean注解或@Component方式实现注册.不能通过程序来选择是否注册。

而实现BeanDefinitionRegistryPostProcessor的类可以获得BeanDefinitionRegistry 对象,通过它可以动态的注册组件,是实现动态注册的钩子函数。spring典型的ConfigurationClassPostProcessor拓展BeanDefinitionRegistryPostProcessor 解析@Configuration配置类 .

spring源码分析系列 (1) spring拓展接口BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor

 public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

     void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

demo示例:

 public class CustomBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {

     @Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition definition = new GenericBeanDefinition();
//设置类
definition.setBeanClass(RegistryBean.class);
//设置scope
definition.setScope("singleton");
//设置是否懒加载
definition.setLazyInit(false);
//设置是否可以被其他对象自动注入
definition.setAutowireCandidate(true); // 给属性赋值
MutablePropertyValues mpv = new MutablePropertyValues() ;
mpv.add("name", "CustomBeanDefinitionRegistry settings") ;
definition.setPropertyValues(mpv); registry.registerBeanDefinition("registryBean", definition);
} @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do noting }
}

CustomBeanDefinitionRegistry.java

 public class LogicBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

     @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("bean") ;
MutablePropertyValues mpv = null ;
if(bd != null && (mpv = bd.getPropertyValues())!=null){
PropertyValue value = mpv.getPropertyValue("name");
System.out.print("修改之前 a 的value是:"+value.getValue()+"\n");
value.setConvertedValue("postProcessBeanFactory修改属性");
}
}
}

LogicBeanFactoryPostProcessor.java

 public class RegistryBean {

     public RegistryBean(){

     }

     public RegistryBean(String name){
this.name = name ;
} private String name ; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "RegistryBean{" +
"name='" + name + '\'' +
'}';
}
}

RegistryBean.java

 <?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="bean" class="com.nancy.ioc.Bean">
<property name="name" value="zhouxiaoxing"/>
</bean> <bean id="logicBeanFactoryPostProcessor" class="com.nancy.ioc.BeanFactoryPostProcessor.LogicBeanFactoryPostProcessor"/>
<bean id="customBeanDefinitionRegistry" class="com.nancy.ioc.BeanFactoryPostProcessor.CustomBeanDefinitionRegistry"/> </beans>

ioc-BeanFactoryPostProcessor.xml

 public class BeanFactoryPostProcessorTest {
private ApplicationContext applicationContext ; @Before
public void beforeApplicationContext(){
/**
* ApplicationContext 自动注册 BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor
* 不需要手动注册
* */
applicationContext = new ClassPathXmlApplicationContext("ioc-BeanFactoryPostProcessor.xml") ;
} @Test
public void test(){
Bean bean = applicationContext.getBean("bean", Bean.class) ;
RegistryBean registryBean = applicationContext.getBean("registryBean", RegistryBean.class) ;
System.out.println(bean);
System.out.println("registryBean :" + JSON.toJSONString(registryBean));
} @After
public void after(){
((ClassPathXmlApplicationContext)applicationContext).close();
}
}

BeanFactoryPostProcessorTest.java

运行结果: 可以看到实现动态的加载 RegistryBean 进入bean容器 和 定制化修改bean definition

修改之前 name 的value是:TypedStringValue: value [zhouxiaoxing], target type [null]
Bean{name='postProcessBeanFactory修改属性'}
registryBean :{"name":"CustomBeanDefinitionRegistry settings"}

详细demo示例可以参考:https://gitee.com/zhouxiaoxing91/learning-src/tree/master/spring-src/src/main/java/com/nancy/ioc

二、BeanFactoryPostProcessor源码分析:注册时机和触发点

注册和触发的入口在AbstractApplicationContext#refresh 容器刷新阶段, 只会调用一次 属于容器级别的拓展接口:

 @Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory); try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context.
// 注册BeanFactoryPostProcessor 在bean definition 加载完成之后
invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory); // Initialize message source for this context.
initMessageSource(); // Initialize event multicaster for this context.
initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses.
onRefresh(); // Check for listener beans and register them.
registerListeners(); // Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event.
finishRefresh();
} catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
} // Destroy already created singletons to avoid dangling resources.
destroyBeans(); // Reset 'active' flag.
cancelRefresh(ex); // Propagate exception to caller.
throw ex;
} finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
} /**
* Instantiate and invoke all registered BeanFactoryPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before singleton instantiation.
*/
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 (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}

这里先说说LoadTimeWeaver(LTW):

在Java 语言中,从织入切面的方式上来看,存在三种织入方式:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器,在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入。

AspectJ采用编译期织入和类加载期织入的方式织入切面,是语言级的AOP实现,提供了完备的AOP支持。它用AspectJ语言定义切面,在编译期或类加载期将切面织入到Java类中。

AspectJ提供了两种切面织入方式,第一种通过特殊编译器,在编译期,将AspectJ语言编写的切面类织入到Java类中,可以通过一个Ant或Maven任务来完成这个操作;第二种方式是类加载期织入,也简称为LTW(Load Time Weaving)。

跟进PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 实例化并触发相关回调:

 public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { // Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 优先触发BeanDefinitionRegistryPostProcessor类型bean, 纪录已经触发回调的beanName
Set<String> processedBeans = new HashSet<String>(); // 1、容器需要具备BeanDefinitionRegistry功能, beanFactoryPostProcessors集合中为容器自身注册的实例, 已知实例集合
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>(); // 1.1、优先触发已知实例集合beanFactoryPostProcessors 中 BeanDefinitionRegistryPostProcessor实例
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
regularPostProcessors.add(postProcessor);
}
} /**
* 1.2、 从beanFactory容器中,获取已经加载的BeanDefinitionRegistryPostProcessor实例,并触发回调
*
* 1.2.1、不会实例化FactoryBeans, 而是留到工厂后置类进行处理. 通过beanFactory.getBeanNamesForType 参数 allowEagerInit 为false控制
* 1.2.2、严格遵循顺序, 触发顺序为实现PriorityOrdered->实现Ordered->普通类型接口
* 1.2.3、同PriorityOrdered、Ordered则以getOrder()返回值排序, 越小优先级别越高
*/
// 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<BeanDefinitionRegistryPostProcessor>(); // 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));
// 纪录已触发实例beanName
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
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);
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);
currentRegistryProcessors.clear();
} // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 1.3、触发所有BeanDefinitionRegistryPostProcessor实例的 postProcessBeanFactory 回调
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 1.4、触发所有BeanFactoryPostProcessor实例的 postProcessBeanFactory 回调
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
} else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
} /**
* 2、 从beanFactory容器中,获取已经加载的BeanFactoryPostProcessor实例,并触发回调
*
* 2.1、不会实例化FactoryBeans, 而是留到工厂后置类进行处理. 通过beanFactory.getBeanNamesForType 参数 allowEagerInit 为false控制
* 2.2、严格遵循顺序, 触发顺序为实现PriorityOrdered->实现Ordered->普通类型接口
* 2.3、同PriorityOrdered、Ordered则以getOrder()返回值排序, 越小优先级别越高
*/
// 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<BeanFactoryPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
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<BeanFactoryPostProcessor>();
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<BeanFactoryPostProcessor>();
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();
}

对应的触发和排序源码:

 private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
Comparator<Object> comparatorToUse = null;
if (beanFactory instanceof DefaultListableBeanFactory) {
comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
}
if (comparatorToUse == null) {
comparatorToUse = OrderComparator.INSTANCE;
}
postProcessors.sort(comparatorToUse);
} /**
* Invoke the given BeanDefinitionRegistryPostProcessor beans.
*/
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) { for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
} /**
* Invoke the given BeanFactoryPostProcessor beans.
*/
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}