SpringBoot源码思考

createApplicationContext

  • 方法:createApplicationContext
  • 作用:创建应用上下文ApplicationContext,注册5个后置处理器
    image
    其中ConfigurationClassPostProcessor扫描器,用来加载@Configuration注解。
  • 实现:
  1. 委派给AnnotationConfigServletWebServerApplicationContext类
  2. 实例化AnnotationConfigServletWebServerApplicationContext类
  3. 委派给AnnotatedBeanDefinitionReader类去实现
  4. 委派给AnnotationConfigUtils类注册注解后置管理器registerAnnotationConfigProcessors

prepareContext

  • 方法:prepareContext
  • 作用:将enviroment设置到context中,使用load方法加载启动类(其他的如设置懒加载和单例加载)
    image
  • 实现:
  1. 调用getAllSources方法加载启动类
  2. 创建BeanDefinitionHolder加载器
  3. load方法直接调用工具类BeanUtils.instantiateClass实例化启动类

invokeBeanFactoryPostProcessors

  • 方法:invokeBeanFactoryPostProcessors
  • 作用:将BeanFactoryPostProcessor注册到BeanFactory上面。加载注解@SpringBootApplication、还递归加载其父类@EnableAutoConfiguration、@Import
    image

image

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	String[] candidateNames = registry.getBeanDefinitionNames();

	// for循环代码干了一件事就是
	// 将@Configuration注解beanFactory后置处理器(ConfigurationClassPostProcessor)放入configCandidates
	for (String beanName : candidateNames) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
			if (logger.isDebugEnabled()) {
				logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
			}
		}
		else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
			configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
		}
	}

	// Return immediately if no @Configuration classes were found
	if (configCandidates.isEmpty()) {
		return;
	}

	// Sort by previously determined @Order value, if applicable
	// 将beanFactory后置处理器根据实现order接口排序
	configCandidates.sort((bd1, bd2) -> {
		int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
		int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
		return Integer.compare(i1, i2);
	});
	
	。。。

	// 解析每一个@Configuration类
	ConfigurationClassParser parser = new ConfigurationClassParser(
			this.metadataReaderFactory, this.problemReporter, this.environment,
			this.resourceLoader, this.componentScanBeanNameGenerator, registry);

	Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
	Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
	do {
		StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
		// 递归处理超类,如META-INF下@EnableAutoConfiguration、@Import
		parser.parse(candidates);
		parser.validate();

		Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
		configClasses.removeAll(alreadyParsed);

		// Read the model and create bean definitions based on its content
		if (this.reader == null) {
			this.reader = new ConfigurationClassBeanDefinitionReader(
					registry, this.sourceExtractor, this.resourceLoader, this.environment,
					this.importBeanNameGenerator, parser.getImportRegistry());
		}
		
		// 加载配置类
		this.reader.loadBeanDefinitions(configClasses);
		alreadyParsed.addAll(configClasses);
		processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

		candidates.clear();
		if (registry.getBeanDefinitionCount() > candidateNames.length) {
			String[] newCandidateNames = registry.getBeanDefinitionNames();
			Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
			Set<String> alreadyParsedClasses = new HashSet<>();
			for (ConfigurationClass configurationClass : alreadyParsed) {
				alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
			}
			for (String candidateName : newCandidateNames) {
				if (!oldCandidateNames.contains(candidateName)) {
					BeanDefinition bd = registry.getBeanDefinition(candidateName);
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
							!alreadyParsedClasses.contains(bd.getBeanClassName())) {
						candidates.add(new BeanDefinitionHolder(bd, candidateName));
					}
				}
			}
			candidateNames = newCandidateNames;
		}
	}
	while (!candidates.isEmpty());

	// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
	if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
		sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
	}

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

finishBeanFactoryInitialization

  • 方法:finishBeanFactoryInitialization
  • 作用:实例化所有非懒加载的类
  • 实现:
  1. 委派给preInstantiateSingletons方法
  2. preInstantiateSingletons方法逻辑:遍历beanNames集合,调用getBean方法实例化(反射调用构造方法 -> 反射调用set方法)

SpringBoot中Bean什么时候实例化?

finishBeanFactoryInitialization方法调用getBean方法中createBeanInstance方法反射实例化bean。

SpringBoot中什么时候属性注入?

createBeanInstance方法反射实例化bean之后,populateBean方法注入属性。

SpringBoot中bean的后置处理器什么时候注册?

refresh方法调用registerBeanPostProcessors方法的时候,注册后置处理器。

SpringBoot中init-method什么时候执行?

在实例化bean和属性填充之后,调用初始化initializeBean方法时,反射执行bean配置的init-method方法。

SpringBoot中bean的前置处理器和后置处理器什么时候执行?

在实例化bean和属性填充之后,调用初始化initializeBean方法时,init-method方法前执行前置处理器,init-method方法后执行后置处理器。

SpringBoot中注解的后置处理器什么时候加载?

run方法中的createApplicationContext方法注册注解到BeanFactory。
image

SpringBoot中注解什么时候加载?

refresh方法中的invokeBeanFactoryPostProcessors方法。在加载@SpringBootApplication注解中的@ComponentScan注解,会扫描路径下的@Component注解的类。

因此注解的加载invokeBeanFactoryPostProcessors方法在实例化操作finishBeanFactoryInitialization方法之前,将@Component的bean类注册到BeanFactory。

SpringBoot中SPI技术加载服务接口

posted @ 2023-04-27 23:58  sunpeiyu  阅读(11)  评论(0编辑  收藏  举报