剑指spring源码(二)

文章目录

  • 剑指spring源码(二)
    • 前言
    • 理解源码的前提环境
    • 源码理解
    • 完整流程分析
    • 总结

剑指spring源码(二)

前言

在我上一篇博客剑指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);

完整流程分析

剑指spring源码(二)_第1张图片

总结

invokeBeanFactoryPostProcessors(beanFactory)确实是主要做执行BeanFactory的后置处理器,其中系统的只有一个,这个后置处理器解析了我们的配置类appConfig,其中很多复杂的问题,例如递归解析,循环import等问题。

你可能感兴趣的:(架构设计,spring)