问题:Spring Boot到底是如何进行自动配置的,都把哪些组件进行了自动配置?
Spring Boot应用的启动入口是@SpringBootApplication注解标注类中的main()方法,
@SpringBootApplication : SpringBoot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main()方法启动SpringBoot应用。
1.SpringBootApplication:
下面,查看@SpringBootApplication内部源码进行分析,核心代码具体如下:
@Target({ElementType.TYPE}) //解的适用范围, Type表示注解可以描述在类、接口、注解或枚举中
@Retention(RetentionPolicy.RUNTIME)//表示注解的生命周期,Runtime运行时
@Documented//表示注解可以记录在javadoc中
@Inherited//表示可以被子类继承该注解
@SpringBootConfiguration//标明该类为配置类
@EnableAutoConfiguration///启动自动配置功能
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
//根据class来排除特定的类,使其不能加入spring容器,传入参数value类型是class类型。
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
//根据classname来排除特定的类,使其不能加入spring容器,传入参数value类型是class的全类名字符串数组。
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
//指定扫描包,参数是包名的字符串数组。
@AliasFor(annotation = ComponentScan.class,attribute = "basePackages")
String[] scanBasePackages() default {};
//扫描特定的包,参数类似是class类型数组。
@AliasFor(annotation = ComponentScan.class,attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
可以看到代码new SpringApplication()
,new了一个这个对象,然后调用run,我们先看看SpringApplication构造函数:
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 把SpringDemoApplication作为primarySources属性存储起来
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 从classpath中推断是否为web应用
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 获取启动加载器
this.bootstrappers = new ArrayList<>(getSpringFactoriesInstances(Bootstrapper.class));
// 设置初始化器(Initializer),最后会调用这些功能
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置监听器(Listener)
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 获取main方法所在的类
this.mainApplicationClass = deduceMainApplicationClass();
}
SpringApplicationRunListener 监听器
监听器的配置与加载
让我们忽略 Spring Boot 计 时和统计的辅助功能,直接来看
SpringApplicationRunListeners获取和使用 SpringApplicationRunL isteners可以理解为一个 SpringApplicationRunListener的容器,它将 SpringApplicationRunListener 的集合以构造方法传入, 并赋值给其 listeners成员变量,然后提供了针对 listeners 成员变量的各种遍历操作方法,比如,遍历集合并调用对应的 starting、started、 running 等方法。
SpringApplicationRunListeners 的构建很简单,中调用的 getRunListeners 方法也只是调用了它的构造方法。SpringApplication 中 getRunListeners 方法代码如下。
private SpringApplicationRunListeners getRunListeners(String[] args) {
//构造 Class 数组
Class<?>[] types = new Class<?>[] { SpringApplication. class, String[].cla
/调用 SpringAppl icat ionRunL isteners 构造方法
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstan
ces
SpringApplicationRunListener .class, types, this, args));}
SpringApplicationRunListeners 构 造 方 法 的 第 二 个 参 数 便 是 SpringApplicationRunL
istener 的 集 合 , SpringApplication 中 调 用 构 造 方 法 时 该 参 数 是 通 过
getSpringFactoriesInstances 方法获取的,代码如下。
private <T> Collection<T> getSpringF actoriesInstances(Class<T> type,
Class<?>[] parameterTypes, object... args) {
//加 META- TNE/sprina. factori es 中对应监听器的配
并将结果存 F'set 中(去重)
Set<Strine> names= newLinkedHashSet<>(
个命的能直,
SpringF actoriesl oader. loadFactoryNames(type, classloader));
/文悯化监听器
List<T> instances = createSpringFactories Instances (type, parameterTypes,
classLoader, args, nam
排序
Annotat ionAwareOrderComparator .sort(instances);
————————————————
版权声明:本文为CSDN博主「写代码的珏秒秒」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_63437643/article/details/123111254
Spring Boot的启动流程分析
Spring Boot的启动流程可以分为以下几个关键步骤:
1.加载配置文件:Spring Boot会根据约定的配置文件名和位置,加载应用程序的配置信息。
2.创建Spring应用上下文:Spring Boot会根据配置信息和依赖关系,创建一个Spring应用上下文实 例。
3.执行自动配置:Spring Boot会根据应用程序的依赖和配置信息,自动配置Spring应用上下文中的各种Bean。
4.启动内嵌服务器:Spring Boot会根据配置信息和依赖关系,启动内嵌的服务器,将应用程序部署到服务器中。
设置应用类型
这个过程非常重要,直接决定了项目的类型,应用类型分为三种,都在WebApplicationType
这个枚举类中,如下:
NONE
:顾名思义,什么都没有,正常流程走,不额外的启动web容器
,比如Tomcat
。SERVLET
:基于servlet
的web程序,需要启动内嵌的servlet
web容器,比如Tomcat
。REACTIVE
:基于reactive
的web程序,需要启动内嵌reactive
web容器,作者不是很了解,不便多说。
启动流程源码解析程图