SpringBoot 自动装配原理解析
该文基于2.0.5.RELEASE版本解析,该文会忽略不相关的源码内容,只关注相关自动装配源码, 关于SpringBoot启动流程源码,麻布会找个时间更新一期
启动类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
实例化 AppicationContext
public ConfigurableApplicationContext run(String... args) {
//...忽略相关代码
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//此处会初始化我们的熟悉的ApplicationContext实例
context = createApplicationContext();
}
//...忽略相关代码
return context;
}
追踪源码, 定位到SpringApplication.run(String… args) 里, 我们看到在ApplicationContext即将被实例化,我们继续往下看
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
SpringBoot 在初始化前会查看应用的上下文是否存在SpringMVC相关依赖,存在将初始化
AnnotationConfigServletWebServerApplicationContext
我们追踪其构造方法
public AnnotationConfigServletWebServerApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
我们继续追踪 AnnotatedBeanDefinitionReader 构造方法进行查看
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
继续追踪
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
//用于处理 @ConditionalOnBean @ConditionalOnClass
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
//为IOC容器注册相关的后置处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
此时自动装配的第一个关键点来了,我们把目光追踪到 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry) 方法中
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
//...忽略相关代码
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
/**
检查IOC容器是否有注册名称为
org.springframework.context.annotation.internalConfigurationAnnotationProcessor的Bean
**/
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//如果不存在, 创建RootBeanDefinition
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
//往IOC容器注册 ConfigurationClassPostProcessor
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
//...忽略相关代码
return beanDefs;
}
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
//往IOC容器注册 BeanDefinition
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
此时注册了ConfigurationClassPostProcessor 到IOC容器, 我们查看该类的的继承关系:
在继承关系里我们看到它实现了 BeanDefinitionRegistryPostProcessor
明白Spring的IOC容器初始化原理的朋友都知道,IOC容器在启动后会优先先加载容器中的后置处理器,并执行后置处理器的方法,我们来回顾下IOC容器的初始化源码:
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 容器初始化前的准备工作
prepareRefresh();
// 初始化 DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 为beanFactory设置容器特性,例如类加载器、事件处理器等
prepareBeanFactory(beanFactory);
try {
//空实现,为容器的某些子类指定特殊的beanPost事件处理器
postProcessBeanFactory(beanFactory);
//调用所有注册的BeanFactoryPostProcessor的bean
invokeBeanFactoryPostProcessors(beanFactory);
//将BeanPostProcessor后置处理器的bean追加到BeanFactory的Bean后置处理器列表中,用于触发bean的生命周期
registerBeanPostProcessors(beanFactory);
//初始化信息源,和国际化相关
initMessageSource();
//初始化容器事件传播器
initApplicationEventMulticaster();
//调用子类的某些特殊bean初始化方法
onRefresh();
//为事件传播器注册事件监听器
registerListeners();
//初始化所有剩余的单例bean
finishBeanFactoryInitialization(beanFactory);
//初始化容器的生命周期时间处理器,并发布容器的生命周期事件
finishRefresh();
}
catch (BeansException ex) {
//...忽略相关代码
}
finally {
//...忽略相关代码
}
}
}
}
我们可以看到 在BeanFactory初始化后,会先执行
invokeBeanFactoryPostProcessors() ,里面的主要逻辑是把BeanFactory里注册的 BeanBeanFactoryPostProcessor 类型的bean优先实例化并进行调用,
ConfigurationClassPostProcessor
该后置处理器的作用是修改IOC容器中的元数据, SpringBoot就是在此加载自动装配类注册到IOC容器中, 接下来我们将目光移到 ConfigurationClassPostProcessor 中
ConfigurationClassPostProcessor
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
//为入参的IOC容器生成唯一的id
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);
}
我们直接定位 postProcessBeanDefinitionRegistry 方法中,修改IOC容器元数据入口在该方法内,在入口处对重复加载会抛异常,继续追踪 processConfigBeanDefinitions
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
//缓存拥有@Configuration注解的bean
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//获取容器中所有已注册的bean名称
String[] candidateNames = registry.getBeanDefinitionNames();
//遍历所有bean
for (String beanName : candidateNames) {
//得到 BeanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//检查 BeanDefinition 是否有包含configurationClass属性的值,有值证明已处理过,则忽略加入缓存
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//检查 BeanDefinition 的目标类是否包含@Configuration 注解
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//追加到缓存中
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// 缓存为空 则忽略
if (configCandidates.isEmpty()) {
return;
}
// 进行排序
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// 从容器中获取自定义的bean名称生成策略
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
/**
如果环境变量为空,则进行初始化,但SpringBoot在初始化 ApplicationContext 之前会初始化Environment ,
并注入到ApplicationContext中,所以下面的条件不会成立
**/
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// 初始化 @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 {
//重点关注该方法,自动装配类的加载在里面完成
parser.parse(candidates);
//校验工作
parser.validate();
//把加载的装配类放到Set中
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
//删除已处理过的自动装配类
configClasses.removeAll(alreadyParsed);
// 初始化 自动装配类的bean读取器 ConfigurationClassBeanDefinitionReader
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
/**
主要逻辑是把装配类的所有被@Bean修饰的方法转换成 ConfigurationClassBeanDefinition 并注册到IOC
**/
this.reader.loadBeanDefinitions(configClasses);
//追加到处理过的自动装配类缓存中
alreadyParsed.addAll(configClasses);
//清空要处理的自动装配类缓存
candidates.clear();
//如果此时IOC容器注册的bean数量大于加载装配类前缓存的bean数量,说明成功注册了新的 BeanDefinition 到IOC容器中
if (registry.getBeanDefinitionCount() > candidateNames.length) {
//IOC容器最新bean名称集合
String[] newCandidateNames = registry.getBeanDefinitionNames();
//老的bean名称集合
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
//初始化处理过的装配类集合
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
//遍历IOC容器最新bean名称集合
for (String candidateName : newCandidateNames) {
//如果老的bean名称集合不包含最新的bean名称
if (!oldCandidateNames.contains(candidateName)) {
//获取对应的BeanDefinition
BeanDefinition bd = registry.getBeanDefinition(candidateName);
//检查BeanDefinition 拥有@Configuration注解 ,并且在处理过的装配类缓存中不存在
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
//追加到candidates缓存,下一次循环会继续处理
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
//往IOC容器注册 自动装配类队列,队列里面包含了符合条件的自动装配类,名称为ConfigurationClassPostProcessor.importRegistry
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();
}
}
从IOC容器遍历所有注册的 BeanDefinition ,并对目标Class的注解进行递归查找拥有@Configuration注解的 BeanDefinition,
第一次加载会加载到启动类对应的BeanDefinition ,我们查看 @SpringBootApplication 源码
会看到@SpringBootConfiguration ,点击查看 @SpringBootConfiguration会看到 @Configuration,此时有些读者会有疑问,在哪里把启动类注册到
IOC容器中,我在这里就不再往前翻源码了,在org.springframework.boot.SpringApplication.prepareContext中注册的,有兴趣的读者可以去看看
重点来了,此时我们把 启动类对应的BeanDefinition 交给 ConfigurationClassParser.parse()进行处理,
在里面会得到所有的自动装配类集合,并把集合交给 ConfigurationClassBeanDefinitionReader.loadBeanDefinitions() 进行 BeanDefinition 注册处理。
我们把目光移到 ConfigurationClassParser.parse() 中继续跟踪源码,查看是如何获取自动装配类
public void parse(Set<BeanDefinitionHolder> configCandidates) {
//初始化缓存集合
this.deferredImportSelectors = new LinkedList<>();
//遍历装配包装类
for (BeanDefinitionHolder holder : configCandidates) {
//得到真正装配类的 BeanDefinition
BeanDefinition bd = holder.getBeanDefinition();
try {
//根据BeanDefinition 的不同实现类,委派给相应的解析方法
if (bd instanceof AnnotatedBeanDefinition) {
parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
}
else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
}
else {
parse(bd.getBeanClassName(), holder.getBeanName());
}
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
}
}
//最后处理DeferredImportSelector的实现类
processDeferredImportSelectors();
}
我们重点关注三个不同的parse()解析方法,可以看到最终是委派给
processConfigurationClass (ConfigurationClass configClass) 进行处理
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//检查装配类是否需要跳过装配
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//检查缓存是否加载过此装配类
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
//如果装配类已加载
if (configClass.isImported()) {
//如果缓存装配类已加载
if (existingClass.isImported()) {
//合并加载类是由哪个装配类带出来的,可以理解为合并装配类的leader
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
//从缓存中删除装配类
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 将装配类转换为 SourceClass
SourceClass sourceClass = asSourceClass(configClass);
/**
开始循环解析 ConfigurationClass 重点关注!
**/
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//缓存装配类
this.configurationClasses.put(configClass, configClass);
}
这里主要做了3个事情
1、检查装配类是否需要跳过装配, 此处用于解析包含 @Conditional 注解的装配类,例如 @ConditionalOnClass @ConditionalOnBean @ConditionalOnProperty
2、检查是否重复加载,如果缓存里存在,则忽略
3、将装配类转换为 SourceClass , 并委派给 doProcessConfigurationClass() 进行解析,如果返回的结果不为空,则继续循环解析
我们先看SpringBoot是如何解析 @Conditional
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
//检查是否包含@Conditional注解
if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
return false;
}
//忽略此处,次数是在 phase 入参为空时,根据 metadata 是否包含@Configuration注解 为phase赋值
if (phase == null) {
if (metadata instanceof AnnotationMetadata &&
ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
}
return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
}
//初始化 Condition 缓存
List<Condition> conditions = new ArrayList<>();
//获取@Condition注解列表, 并获取value属性转换为列表
for (String[] conditionClasses : getConditionClasses(metadata)) {
for (String conditionClass : conditionClasses) {
//实例化 Condition 实现类
Condition condition = getCondition(conditionClass, this.context.getClassLoader());
//追加缓存
conditions.add(condition);
}
}
//排序
AnnotationAwareOrderComparator.sort(conditions);
//遍历 Condition 缓存
for (Condition condition : conditions) {
ConfigurationPhase requiredPhase = null;
if (condition instanceof ConfigurationCondition) {
requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
}
//调用condition.matches 如果返回false,则表示需要跳过
if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
return true;
}
}
return false;
}
上面主要获取装配类的所有 @Conditional 注解的 value 属性 ,并进行实例化,得到一组Condition 实现类, 最后进行遍历,依次调用 Condition.match() ,如果其中1个实现类返回false,则表示该装配类需要跳过 , 我们点击跟踪 SpringBootCondition 查看 match() 源码
public final boolean matches(ConditionContext context,
AnnotatedTypeMetadata metadata) {
//获取类名或者方法名
String classOrMethodName = getClassOrMethodName(metadata);
try {
//获取是否匹配结果
ConditionOutcome outcome = getMatchOutcome(context, metadata);
//打印日志
logOutcome(classOrMethodName, outcome);
recordEvaluation(context, classOrMethodName, outcome);
//返回是否匹配
return outcome.isMatch();
}
catch (NoClassDefFoundError ex) {
//忽略相关代码
}
catch (RuntimeException ex) {
//忽略相关代码
}
}
getMatchOutcome() 是抽象方法 , 因为SpringBoot提供了很多 @ConditionOnXXX 注解 这些注解都对应一个实现类,实现了matches 方法,我们拿 @ConditionalOnClass 举例
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
Class<?>[] value() default {};
/**
* The classes names that must be present.
* @return the class names that must be present.
*/
String[] name() default {};
}
可以看到 @Conditional 注解的值为 OnClassCondition , 我们进入 OnClassCondition 查看
getMatchOutcome 实现逻辑
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ClassLoader classLoader = context.getClassLoader();
ConditionMessage matchMessage = ConditionMessage.empty();
//获取@ConditionalOnClass注解的value值并转换为String
List<String> onClasses = getCandidates(metadata, ConditionalOnClass.class);
//如果onClasses不为空
if (onClasses != null) {
//得到上下文中不存在的class集合
List<String> missing = getMatches(onClasses, MatchType.MISSING, classLoader);
//如果missing不为空, 证明依赖的Class不存在,返回ConditionOutcome.noMatch
if (!missing.isEmpty()) {
return ConditionOutcome
.noMatch(ConditionMessage.forCondition(ConditionalOnClass.class)
.didNotFind("required class", "required classes")
.items(Style.QUOTE, missing));
}
matchMessage = matchMessage.andCondition(ConditionalOnClass.class)
.found("required class", "required classes").items(Style.QUOTE,
getMatches(onClasses, MatchType.PRESENT, classLoader));
}
//获取 @ConditionalOnMissingClass 注解的value值并转换为String
List<String> onMissingClasses = getCandidates(metadata,
ConditionalOnMissingClass.class);
if (onMissingClasses != null) {
//得到上下文中存在的class集合
List<String> present = getMatches(onMissingClasses, MatchType.PRESENT,
classLoader);
//如果 present 不为空, 证明需要不存在的Class反而存在,返回ConditionOutcome.noMatch
if (!present.isEmpty()) {
return ConditionOutcome.noMatch(
ConditionMessage.forCondition(ConditionalOnMissingClass.class)
.found("unwanted class", "unwanted classes")
.items(Style.QUOTE, present));
}
matchMessage = matchMessage.andCondition(ConditionalOnMissingClass.class)
.didNotFind("unwanted class", "unwanted classes").items(Style.QUOTE,
getMatches(onMissingClasses, MatchType.MISSING, classLoader));
}
//走到这里,证明满足条件,返回 ConditionOutcome.match
return ConditionOutcome.match(matchMessage);
}
这里会获取装配类的 @ConditionalOnClass 的value值,并转换为 String , 从类加载器中查看
是否包含 onClasses ,如果其中一个不包含,则返回 ConditionOutcome.noMatch() 不匹配规则, 如果匹配继续往下走,
获取装配类的 @ConditionalOnMissingClass 的value值,并转换为 String , 从类加载器中查看是否不包含 **onMissingClasses ** 如果其中一个包含,则返回 ConditionOutcome.noMatch() 不匹配规则
这2个条件都满足则返回 ConditionOutcome.match() 匹配成功
我们回到 processConfigurationClass() 中, 继续追踪
protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
//检查装配类是否需要跳过装配
if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
return;
}
//检查缓存是否加载过此装配类
ConfigurationClass existingClass = this.configurationClasses.get(configClass);
if (existingClass != null) {
//如果装配类已加载
if (configClass.isImported()) {
//如果缓存装配类已加载
if (existingClass.isImported()) {
//合并加载类是由哪个装配类带出来的,可以理解为合并装配类的leader
existingClass.mergeImportedBy(configClass);
}
// Otherwise ignore new imported config class; existing non-imported class overrides it.
return;
}
else {
//从缓存中删除装配类
this.configurationClasses.remove(configClass);
this.knownSuperclasses.values().removeIf(configClass::equals);
}
}
// 将装配类转换为 SourceClass
SourceClass sourceClass = asSourceClass(configClass);
/**
开始循环解析sourceClass
**/
do {
sourceClass = doProcessConfigurationClass(configClass, sourceClass);
}
while (sourceClass != null);
//缓存装配类
this.configurationClasses.put(configClass, configClass);
}
我们将目光移到,将装配类转换为 SourceClass , 并委派给 doProcessConfigurationClass() 进行解析,如果返回的结果不为空,则继续循环解析
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
throws IOException {
//检查是否有Component注解, 如果拥有的话, 遍历其内部类拥有@Configuration注解的类,递归processConfigurationClass()解析
if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
processMemberClasses(configClass, sourceClass);
}
// 检查是否有 @PropertySource 注解 ,有的话则加载配置文件, 追加到环境变量 Environment 中
for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), PropertySources.class,
org.springframework.context.annotation.PropertySource.class)) {
if (this.environment instanceof ConfigurableEnvironment) {
processPropertySource(propertySource);
}
else {
logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
"]. Reason: Environment must implement ConfigurableEnvironment");
}
}
// 获取 @ComponentScan 注解配置信息
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
//检查是否拥有 @ComponentScan 注解信息,并且满足加载条件 进入扫描代码块
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
/**
委派给 ComponentScanAnnotationParser 把带有自动装配注解的类(例如:@Compoent @Service)扫描出来,并加载到IOC容器中,
因为 @SpringBootApplication 注解中包含了 @ComponentScan 注解, 所以会扫描启动类所在包下的所有类
**/
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
// 遍历扫描出来的元数据 BeanDefinitionHolder
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
//检查扫描的类是否包含 @Configuration ,包含则优先解析扫描出来的 ConfigurationClass 配置类
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
/**
处理 @Import 注解, 主要逻辑是:
1、遍历 @Import 的值
2、判断值的所属类型
2.1、如果是ImportSelector的实现类,则调用 selectImports() 返回 一组配置类递归给 processImports() 方法加载
2.2、如果是 DeferredImportSelector 的实现类,则加载到 deferredImportSelectors 内存中 ,延迟加载
2.3、如果是 ImportBeanDefinitionRegistrar 的实现类,则会追加到对应的 ConfigurationClass 的importBeanDefinitionRegistrars属性中
最后在ConfigurationClassParser.loadBeanDefinitions() 对所有ConfigurationClass进行加载时,
会调用 ImportBeanDefinitionRegistrar.registerBeanDefinitions() 通过编码的方式扩展,加载Bean元数据
2.4、如果都不是,当成一个配置类, 递归processConfigurationClass() 加载解析
我们重点关注 DeferredImportSelector , 因为 @EnableAutoConfiguration 注解里导入的类是 AutoConfigurationImportSelector
**/
processImports(configClass, sourceClass, getImports(sourceClass), true);
/**
处理 @ImportResource 注解, 把spring的bean配置文件缓存到 ConfigurationClass.importedResources中,
最后在ConfigurationClassParser.loadBeanDefinitions() 对所有ConfigurationClass进行加载时,会使用 XmlBeanDefinitionReader 进行解析加载
**/
AnnotationAttributes importResource =
AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
String[] resources = importResource.getStringArray("locations");
Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
for (String resource : resources) {
String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
configClass.addImportedResource(resolvedResource, readerClass);
}
}
// 处理 带有 @Bean 注解修饰的方法, 并缓存到 ConfigurationClass.beanMethods
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// 没太明白做的逻辑, 以后再说
processInterfaces(configClass, sourceClass);
// 查看是否拥有父类, 并且父类不是java开头的包, 则返回父类,循环加载父类配置信息
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (superclass != null && !superclass.startsWith("java") &&
!this.knownSuperclasses.containsKey(superclass)) {
this.knownSuperclasses.put(superclass, configClass);
// Superclass found, return its annotation metadata and recurse
return sourceClass.getSuperClass();
}
}
// 没有父类, 外层循环结束
return null;
}
我们把目光移到 ConfigurationClassParser.parse() 代码块里的
processDeferredImportSelectors();
中继续跟踪源码,查看是如何获取要自动装配的配置类
public void process() {
List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
//构造 DeferredImportSelectorGroupingHandler
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
//对deferredImports进行排序
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
/**
遍历 deferredImports 并依次调用handler.register(DeferredImportSelectorHolder holder)
在里面主要获取DeferredImportSelector.getImportGroup() 类型, 实例化后 保存到DeferredImportSelectorGroupingHandler.groupings属性中
**/
deferredImports.forEach(handler::register);
/**
依次调用
DeferredImportSelector.Group.process() 在这里面会去加载spring.factories配置文件中key=EnableAutoConfiguration的配置项,
并封装成一组配置集合,并对其进行过滤, 过滤掉一些不符合加载条件的配置类
DeferredImportSelector.Group.selectImports() 会对配置集合进行排序, 根据这几个注解进行排序 :
@Order @AutoConfigureBefore @AutoConfigureAfter
**/
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
解析handler.processGroupImports
public void processGroupImports() {
//遍历注册在缓存中的DeferredImportSelector的包装类
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
//grouping.getImports() 主要是加载spring.factories的自动装配类,并对其过滤 排序
grouping.getImports().forEach(entry -> {
ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata());
try {
//正式开始加载自动装配类 我们比较熟悉的RedisAutoConfiguration RabbitAutoConfiguration就是在这里进行装配的
processImports(configurationClass, asSourceClass(configurationClass),
asSourceClasses(entry.getImportClassName()), false);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanDefinitionStoreException(
"Failed to process import candidates for configuration class [" +
configurationClass.getMetadata().getClassName() + "]", ex);
}
});
}
}