springBoot学习笔记源码分析之@springbootApplication
Posted 拐柒
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springBoot学习笔记源码分析之@springbootApplication相关的知识,希望对你有一定的参考价值。
springBoot学习笔记(二)源码分析
源码剖析之@springbootApplication
springboot-starter
我们在创建springboot项目中pom.xml中不需要进行依赖的版本配置,是因为在springboot-starter-parent的父级spring-boot-dependencies中已经替我们配置好了一些第三方框架的依赖。如果我们使用的第三方框架没有和springboot进行集成,这个时候我们就需要进行版本配置。
springboot自动配置之@springbootApplication
根据我们添加的jar依赖,springboot会自动的将一些配置类和的bean注册进ioc容器中,我们可以在需要的地方使用@autowried或者@Resource注解来使用他。
@SpringBootConfiguration
@SpringBootApplication是一个组合注解。其中@SpringBootConfiguration表明了SpringBootApplication是一个配置类,被SpringBootApplication标注的类,是主配置类。
@EnableAutoConfiguration
@EnableAutoConfiguration注解也是一个组合注解,由@AutoConfigurationPackage,@Import(AutoConfigurationImportSelector.class)构成。
Spring 中有很多以 Enable 开头的注解,其作用就是借助 @Import 来收集并注册特定场景相关的Bean ,并加载到 IOC 容器。
@EnableAutoConfiguration就是借助@Import来收集所有符合自动配置条件的bean定义,并加载到
IoC容器。
@AutoConfigurationPackage
package org.springframework.boot.autoconfigure;
@Import(AutoConfigurationPackages.Registrar.class) // 导入Registrar中注册的组件
public @interface AutoConfigurationPackage { }
@AutoConfigurationPackage :自动配置包,它也是一个组合注解,其中最重要的注解是@Import(AutoConfigurationPackages.Registrar.class) ,它是 Spring 框架的底层注解,它的作用就是给容器中导入某个组件类,例如
@Import(AutoConfigurationPackages.Registrar.class) ,它就是将 Registrar 这个组件类导入到容器中。AutoConfigurationPackages.Registrar这个类就干一个事,注册一个 Bean ,这个 Bean 就是org.springframework.boot.autoconfigure.AutoConfigurationPackages.BasePackages ,它有一个参数,这个参数是使用了 @AutoConfigurationPackage 这个注解的类所在的包路径,保存自动配置类以供之后的使用。
@Import(AutoConfigurationImportSelector.class)
AutoConfigurationImportSelector中的内部类AutoConfigurationGroup主要用来处理自动配置相关的逻辑,拥有peocess和selectImports方法。
process方法
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
getAutoConfigurationEntry方法
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//1、获取所有META-INF 下spring.factory文件中 key为 EnableAutoConfiguration注解全路径的value值,即为需要装配的所有配置文件全限定类名
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//2、去重
configurations = removeDuplicates(configurations);
//3、排除一些全限定类名,即添加在@springbootappliciton(exclude = "xxx")中的class
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//4、检查排除的类名是不是一个配置类
checkExcludedClasses(configurations, exclusions);
//5、进行排除
configurations.removeAll(exclusions);
//6、因为从spring.factories文件获取的自动配置类太多,如果有些不必要的自动配置类都加载 进内存,会造成内存浪费,因此这里需要进行过滤
// 注意这里会调用AutoConfigurationImportFilter的match方法来判断是否符合 @ConditionalOnBean,@ConditionalOnClass或@ConditionalOnWebApplication
//即判断是否符合以@Conditional注解开头的注解条件,例如@ConditionalOnClass(RibbitMQ.Class),即判断classpath下是不是引入了mq相关的jar
configurations = filter(configurations, autoConfigurationMetadata);
// 7 、获取了符合条件的自动配置类后,此时触发AutoConfigurationImportEvent事件,
// 目的是告诉ConditionEvaluationReport条件评估报告器对象来记录符合条件的自动配置类
// 该事件什么时候会被触发?--> 在刷新容器时调用invokeBeanFactoryPostProcessors后置处 理器时触发
fireAutoConfigurationImportEvents(configurations, exclusions);
// 8、将符合条件和要排除的自动配置类封装进AutoConfigurationEntry对象,并返回
return new AutoConfigurationEntry(configurations, exclusions);
}
@ComponentScan
如果没有指定basePackages属性,那么springboot启动时候便会扫描被@ComponentScan标注类的所在包。
以上是关于springBoot学习笔记源码分析之@springbootApplication的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot源码分析----SpringBoot自动配置
SpringBoot配置外部Tomcat项目启动流程源码分析(上)