在我上一篇博客剑指spring源码(一)中介绍了spring的bd注册过程,本文主要讲的是第三行代码refresh()中的invokeBeanFactoryPostProcessors(beanFactory);这一行代码,顾名思义,这行代码的作用是执行bean工厂的后置处理器,当然这行代码的作用可不止这一点。我的理解是spring对bean工厂提供了一系列扩展接口,我们可以通过实现这些接口来干扰spring bean工厂的实例化过程。源码学习实在是太枯燥,很难看懂,我也不知道怎么写才能让别人看的懂,写的过程非常焦灼,写的可能不是很好,多多见谅。
入口类
public static void main(String[] args) {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext();
app.register(AppConfig.class);
//下面两个会放到一个list集合里
app.addBeanFactoryPostProcessor(new MyBeanDefinitionRegistryPostProcessor());
app.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
app.refresh();
}
全配置类
@Import(ImportService.class)
@ComponentScan("com.lry")
@Configuration//加了全配置注解会被cglib增强
public class AppConfig {
}
几个服务类
@Service
//@Import(OrderService.class) 测试循环Import
public class UserService {
}
@Service
//@Import(UserService.class) 测试循环Import
public class OrderService {
}
public class ImportService {
}
spring提供了BeanDefinitionRegistryPostProcessor ,BeanFactoryPostProcessor 这两个接口扩展bean factory
其中BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println(registry.getBeanDefinitionNames());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println(beanFactory);
}
}
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println(beanFactory);
}
}
从refresh()中的invokeBeanFactoryPostProcessors(beanFactory);点进去的核心代码如下
//beanFactory是this里面new出来的
//getBeanFactoryPostProcessors()返回的是我的入口类app添加的两个postProcessors
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
再次点进去的代码如下
//已经注册的bean的beanName集合(已经添加到单例池的bean)
Set<String> processedBeans = new HashSet<>();
//this.beanFactory = new DefaultListableBeanFactory();
//DefaultListableBeanFactory implements BeanDefinitionRegistry
//所以这个if一定会进
if (beanFactory instanceof BeanDefinitionRegistry) {
//强转
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//常规BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//BeanDefinitionRegistryPostProcessor 在BeanFactoryPostProcessor 的基础上扩展了一个接口
//BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//beanFactoryPostProcessors是我们手动add进去的两个PostProcessors
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
//强转
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//这里会回调我们实现BeanDefinitionRegistryPostProcessor的类的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
//添加BeanDefinitionRegistryPostProcessor
registryProcessors.add(registryProcessor);
}
else {
//添加BeanFactoryPostProcessor
regularPostProcessors.add(postProcessor);
}
}
//执行到这里regularPostProcessors和registryProcessors容器分别有一个元素
//currentRegistryProcessors存的是spring内部的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//getBeanNamesForType 顾名思义 就是根据类型获取beanNames
//也就是把之前容器注册的5个bd其中类型是BeanDefinitionRegistryPostProcessor的beanName返回过来
//这5个bd中有一个beanName=org.springframework.context.annotation.internalConfigurationAnnotationProcessor
//类型是ConfigurationClassPostProcessor的bd
//然而ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor
//所以这个postProcessorNames数组只有一个元素就是这个beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//添加到currentRegistryProcessors 集合 ,
//其中beanFactory.getBean 及其重要,里面也极其复杂,如果beanFactory有这个bean会直接返回,
//如果没有他会创建对象放到beanFactory单例池中,再返回,另外这里还要解决循环引用问题
//限于篇幅,getBean 在本文不会涉及,下次有机会再说
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//添加到已经注册bean的集合
processedBeans.add(ppName);
}
}
//到此为止currentRegistryProcessors,registryProcessors,regularPostProcessors各有一个元素
//执行系统的BeanDefinitionRegistryPostProcessors,只有一个
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
上面这行代码最终会调用ConfigurationClassPostProcessor里面的processConfigBeanDefinitions方法,内容如下,我只会挑一些关键的地方说。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取容器中所有的bd name ,有6个 :5个root bd+appConfig
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//检查这个bd描述的类是否是配置类 也就是加了@Configuration的类
//往细里说 其实是
//if @Configuration->FULL
// else if @ImportResource @Import @Component @ComponentScan->LITE
//由于系统的5个root bd肯定不是配置类,所以configCandidates只有一个元素就是appConfig
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//解析器 解析appConfig
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//candidates list->set将configCandidates去重
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
//已经处理过的配置类的集合
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
parser.parse(candidates);//解析配置类,核心代码在这
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
}
parser.parse(candidates);解析器解析appConfig的代码如下
解析器解析最终会调用ConfigurationClassPostProcessor里的doProcessConfigurationClass方法,核心代码如下
// Process any @ComponentScan annotations 处理ComponentScan注解
//我的appConfig有ComponentScan 所以下面这个set有一个元素
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
//set集合不空&&appConfig不要跳过解析(condition注解不会的可以学一下,这里就可以看懂了)
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
//根据appConfig的componentScan注解的value,扫描这个value代表的包下的所有类得到 bd集合
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
//遍历得到的bd 集合,遍历干什么? 因为这些bd可能还是配置类,如果还是配置类,那么还需要对这些bd进行递归的解析
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//是否配置类 ,是->递归调用
//@Configuration->FULL 全配置类
//@ImportResource @Import @Component @ComponentScan->LITE 半配置类
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)){
parse(bdCand.getBeanClassName(), holder.getBeanName());//递归解析
}
}
}
}
// Process any @Import annotations
//这行代码又是一行非常难的代码,不仅要考虑Import注解(import分好几种,处理方式都不同),还要考虑循环Import的问题
processImports(configClass, sourceClass, getImports(sourceClass), true);
处理import的核心代码如下
//是否检查循环import&&是否循环import
//如果有循环import就报错
if (checkForCircularImports && isChainedImportOnStack(configClass)) {
this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
}
else {
//入栈
this.importStack.push(configClass);
try {
for (SourceClass candidate : importCandidates) {
//不展开讲了,下次再写一篇补充博客讲解ImportSelector和ImportBeanDefinitionRegistrar
if (candidate.isAssignable(ImportSelector.class)) {
//ImportSelector的处理方式
}
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
//ImportBeanDefinitionRegistrar的处理方式
}
else {//不是上面这两种就默认作为配置类处理
//registerImport就是添加到一个imports集合中
this.importStack.registerImport(
currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
processConfigurationClass(candidate.asConfigClass(configClass));//又回到了上面说解析配置类的代码
}
}
}
ImportSelector补充篇
ImportBeanDefinitionRegistrar补充篇
到这里为止就差不多分析完了,再回到PostProcessorRegistrationDelegate的invokeBeanFactoryPostProcessors方法
//这两行代码就是回调MyBeanFactoryPostProcessor和MyBeanDefinitionRegistryPostProcessor的重写方法postProcessBeanFactory
//以及ConfigurationClassPostProcessor里面的重写方法postProcessBeanFactory
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(beanFactory)确实是主要做执行BeanFactory的后置处理器,其中系统的只有一个,这个后置处理器解析了我们的配置类appConfig,其中很多复杂的问题,例如递归解析,循环import等问题。