SpringBoot刷新上下文一共七篇,基于SpringBoot 2.2.7.RELEASE,Spring 5.2.6.RELEASE
SpringBoot 刷新上下文1–主流程
SpringBoot 刷新上下文2–执行BeanDefinitionRegistryPostProcessor
SpringBoot 刷新上下文3–解析引导类
SpringBoot 刷新上下文4–处理ComponentScan
SpringBoot 刷新上下文5–处理其他注解
SpringBoot 刷新上下文6–加载并注册BeanDefinition
SpringBoot 刷新上下文7–执行BeanFactoryPostProcessor
接前篇,调用BeanDefinitionRegistryPostProcessors,这里主要是执行了ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry 。
//org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors
private static void invokeBeanDefinitionRegistryPostProcessors(
Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {
//ConfigrationClassPostProsessor
for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanDefinitionRegistry(registry);
}
}
private final Set<Integer> registriesPostProcessed = new HashSet<>();
//org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
int registryId = System.identityHashCode(registry);
// 这里做了一个防重
if (this.registriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
}
if (this.factoriesPostProcessed.contains(registryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
}
// 加入缓存
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
}
处理配置类
private ConfigurationClassBeanDefinitionReader reader;
//org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//候选的配置类 BeanDefinitionHolder 集合
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取候选BeanDefinitionName 这里包含引导类 其他类BeanN都是全名,是Spring内置配置类
//candidateNames = {String[7]@4153}
// 0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
// 1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
// 2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
// 3 = "org.springframework.context.event.internalEventListenerProcessor"
// 4 = "org.springframework.context.event.internalEventListenerFactory"
// 5 = "Application"
// 6 = "org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory"
String[] candidateNames = registry.getBeanDefinitionNames();
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
// 按 order 排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
//registry = DefaultListableBeanFactory
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
//CONFIGURATION_BEAN_NAME_GENERATOR = "org.springframework.context.annotation.internalConfigurationBeanNameGenerator"
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
//environment 已经初始化过了
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
// 创建Configuration 类的解析器 @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 {
//解析 @Configuration 标注类,这里会解析引导类
parser.parse(candidates);
//处理 error 等 problemReporter
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);
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();
}
}
这里会先检查候选类,如果候选类为空,则结束。
解析候选类,包括Spring内建Bean和SpringBoot的引导类。
加载并注册。
//org.springframework.context.annotation.ConfigurationClassUtils#checkConfigurationClassCandidate
public static boolean checkConfigurationClassCandidate(
BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
//获取Class名称,这里还是处理的引导类
String className = beanDef.getBeanClassName();
if (className == null || beanDef.getFactoryMethodName() != null) {
return false;
}
AnnotationMetadata metadata;
//是否是被注解标注类
if (beanDef instanceof AnnotatedBeanDefinition &&
className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
// Can reuse the pre-parsed metadata from the given BeanDefinition...
// 获取注解元信息
metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
}
else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
// Check already loaded Class if present...
// since we possibly can't even load the class file for this Class.
Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
BeanPostProcessor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
EventListenerFactory.class.isAssignableFrom(beanClass)) {
return false;
}
metadata = AnnotationMetadata.introspect(beanClass);
}
else {
try {
MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
metadata = metadataReader.getAnnotationMetadata();
}
catch (IOException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Could not find class file for introspecting configuration annotations: " +
className, ex);
}
return false;
}
}
//获取 @Configuration 标注元信息
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
//proxyBeanMethods 属性不为空
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
//org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass
//full
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
// 被其他注解标注
else if (config != null || isConfigurationCandidate(metadata)) {
//lite
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
else {
return false;
}
// It's a full or lite configuration candidate... Let's determine the order value, if any.
//获取 order
Integer order = getOrder(metadata);
if (order != null) {
beanDef.setAttribute(ORDER_ATTRIBUTE, order);
}
return true;
}
这个方法判断如果类没有被注解标注,就返回false。
引导类是被 @SpringBootApplication标注的,@SpringBootApplication 被@SpringBootConfiguration 标注,@SpringBootConfiguration 被 @Configuration 标注,所以引导类是候选类。
@Configuration注解中proxyBeanMethods 默认是true,所以引导类BeanDefinition属性中org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass 是 full。
如果@Configuration 注解 proxyBeanMethods 设置成false,则不是候选类,否则会判断是否被下面的五个注解(@Component, @ComponentScan, @Import, @ImportResource, @Bean)标注,如果被下面的五个注解标注了,也是候选类,BeanDefinition属性中org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass 是 lite。
private static final Set<String> candidateIndicators = new HashSet<>(8);
static {
candidateIndicators.add(Component.class.getName());
candidateIndicators.add(ComponentScan.class.getName());
candidateIndicators.add(Import.class.getName());
candidateIndicators.add(ImportResource.class.getName());
}
//org.springframework.context.annotation.ConfigurationClassUtils#isConfigurationCandidate
public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
// Do not consider an interface or an annotation...
if (metadata.isInterface()) {
return false;
}
// Any of the typical annotations found?
for (String indicator : candidateIndicators) {
if (metadata.isAnnotated(indicator)) {
return true;
}
}
// Finally, let's look for @Bean methods...
try {
return metadata.hasAnnotatedMethods(Bean.class.getName());
}
catch (Throwable ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
}
return false;
}
}
//org.springframework.context.annotation.ConfigurationClassUtils#getOrder(org.springframework.core.type.AnnotationMetadata)
public static Integer getOrder(AnnotationMetadata metadata) {
Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
}
//元数据读取器工厂
private final MetadataReaderFactory metadataReaderFactory;
//spi 处理error 和 warn
private final ProblemReporter problemReporter;
private final Environment environment;
private final ResourceLoader resourceLoader;
private final BeanDefinitionRegistry registry;
//扫描注解解析器
private final ComponentScanAnnotationParser componentScanParser;
//condition 解析器
private final ConditionEvaluator conditionEvaluator;
public ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, ProblemReporter problemReporter, Environment environment, ResourceLoader resourceLoader, BeanNameGenerator componentScanBeanNameGenerator, BeanDefinitionRegistry registry) {
this.metadataReaderFactory = metadataReaderFactory;
this.problemReporter = problemReporter;
this.environment = environment;
this.resourceLoader = resourceLoader;
this.registry = registry;
this.componentScanParser = new ComponentScanAnnotationParser(
environment, resourceLoader, componentScanBeanNameGenerator, registry);
this.conditionEvaluator = new ConditionEvaluator(registry, environment, resourceLoader);
}