Spring 5.x 源码之旅九invokeBeanFactoryPostProcessors二

ConfigurationClassParser加载bean定义还有一点尾巴

循环解析加载bean定义

上一篇讲了是一次解析加载bean定义的过程,其实外面是个循环,因为你加载了bean定义后,可能会有新的配置类的bean定义,所以也要进行解析和加载bean,因此是一个循环。我省略了部分代码,把主要的循环流程和判断留下来了。其实就是循环处理新加载进来的配置类的bean定义,直到没有为止。

		do {//开始解析configCandidates元素
			parser.parse(candidates);//解析配置类集合
			parser.validate();//验证如果要CGLIB代理的话,条件是否满足,比如类不能final,bean注解		
			this.reader.loadBeanDefinitions(configClasses);//加载bean定义
			...
			if (registry.getBeanDefinitionCount() > candidateNames.length) {//如果有加载到新的bean定义,再继续加载
				...
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {//处理新的
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {//符合配置类要求就添加到candidates
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;//更新候选名字
			}
		}
		while (!candidates.isEmpty());

注册单例importStack

importStack注册为单例,为了支持ImportAware接口扩展,说明已经处理Import注解过了。

if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

清除字节码元数据缓存

有些bean定义的元数据是通过URL加载字节码文件解析来的,为了避免每次都去IO操作,会有元数据的缓存,现在处理完了就要把缓存清除了。

if (this.metadataReaderFactory instanceof 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) this.metadataReaderFactory).clearCache();
		}

BeanDefinitionRegistryPostProcessor后置处理器处理流程

在这里插入图片描述

处理一般排序的BeanDefinitionRegistryPostProcessor后置处理器

至此ConfigurationClassPostProcessor的处理完成了,也就是有优先级PriorityOrdered的后置处理器处理好了,现在要处理一般顺序Ordered的处理器了,这段代码跟前面的一样,只是这次是取一般顺序的处理器,执行的是一样的流程,这里还是再次获取BeanDefinitionRegistryPostProcessor类型的,会把所有的都获取出来,当然包括处理过的,不过没关系,处理过的处理器会放入processedBeans中,不会再次处理的:

//再次获取没处理过的BeanDefinitionRegistryPostProcessors且实现Ordered接口的来处理,因为可能前面处理后产生新的bean定义
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				//没处理过的,而且是Ordered类型的
				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);

其实这里也可能是PriorityOrdered类型的,是通过前面解析出来的。比如我们来看这个扩展点。

扩展点实战一

比如创建了一个TestBeanDefinitionRegistryPostProcessorPriorityOrdered 实现了BeanDefinitionRegistryPostProcessorOrdered

public class TestBeanDefinitionRegistryPostProcessorPriorityOrdered implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
    public TestBeanDefinitionRegistryPostProcessorPriorityOrdered(){
        System.out.println("TestBeanDefinitionRegistryPostProcessorPriorityOrdered被创建了");
    }

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanDefinitionRegistry");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanFactory");
    }
    //排序的值,越小越前面
    @Override
    public int getOrder() {
        return 1;
    }
}

然后配置类里面用bean注解方法,直接返回这个实例类型,我这里为了方便,其实应该返回接口类型,另外写一个接口类型比较好的。

@Configuration
public class MyConfig {
    @Bean
    public TestBeanDefinitionRegistryPostProcessorPriorityOrdered myRegistrar(){
        return  new TestBeanDefinitionRegistryPostProcessorPriorityOrdered();
    }
}

执行的结果就是会被创建出来,然后执行postProcessBeanDefinitionRegistry方法:
在这里插入图片描述
在这里插入图片描述

注意

这里要注意,这个时候因为要创建TestBeanDefinitionRegistryPostProcessorPriorityOrdered处理器,所以MyConfig也会被创建出来,作为单例。

循环处理最后剩下的BeanDefinitionRegistryPostProcessor后置处理器

最后就处理剩下的那些后置处理器,比如我在前面的扩展点再注册bean定义。

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();
			}

扩展点实战二

还是刚才的TestBeanDefinitionRegistryPostProcessorPriorityOrdered ,我在postProcessBeanDefinitionRegistry里自定义注册了一个bean定义TestBeanDefinitionRegistryPostProcessor
他就会在最后被getBeanNamesForType找到执行。

public class TestBeanDefinitionRegistryPostProcessorPriorityOrdered implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
    public TestBeanDefinitionRegistryPostProcessorPriorityOrdered() {
        System.out.println("TestBeanDefinitionRegistryPostProcessorPriorityOrdered被创建了");
    }


    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanDefinitionRegistry");
        AnnotatedBeanDefinition genericBeanDefinition=new AnnotatedGenericBeanDefinition(TestBeanDefinitionRegistryPostProcessor.class);
        registry.registerBeanDefinition("TestBeanDefinitionRegistryPostProcessor",genericBeanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessorPriorityOrdered postProcessBeanFactory");
    }

    //排序的值,越小越前面
    @Override
    public int getOrder() {
        return 1;
    }
}

TestBeanDefinitionRegistryPostProcessor 也是BeanDefinitionRegistryPostProcessor 类型的,扩展方法里又注册了一个UserDaoImple

public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor postProcessBeanDefinitionRegistry");
        registry.registerBeanDefinition("UserDaoImple",new AnnotatedGenericBeanDefinition(UserDaoImple.class));
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor postProcessBeanFactory");
    }
}

结果:
在这里插入图片描述
在这里插入图片描述
而且在里面又注册了一个UserDaoImple
在这里插入图片描述
至此,所有实现的BeanDefinitionRegistryPostProcessor接口的处理器都处理完成了。
我们的自定义扩展顺序可以看这里:
在这里插入图片描述

扩展点顺序

ConfigurationClassPostProcessor处理MyConfigMyConfig定义了TestBeanDefinitionRegistryPostProcessorPriorityOrderedbean注解方法,可以被加载进bean定义。
在这里插入图片描述
TestBeanDefinitionRegistryPostProcessorPriorityOrderedpostProcessBeanDefinitionRegistry方法中注册了TestBeanDefinitionRegistryPostProcessorbean定义。
在这里插入图片描述
TestBeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry又注册了UserDaoImplebean定义。
在这里插入图片描述

注意

这个时候你会发现创建处理器的同时把配置类也创建了。
在这里插入图片描述

至此BeanDefinitionRegistryPostProcessor的处理器全部处理完成,包括自定义的。后面就要处理BeanFactoryPostProcessor的处理器啦,这个后面讲。

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值