运行原理的初步认识
我们之前写HelloSpringBoot,是怎样运行的那,Maven项目,我们从pom.xml文件开始吧。
pom.xml
父依赖
其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件!
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
在点进去,还有一个父依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.1.0</version>
</parent>
这里才是真正管理springBoot应用里面所有依赖的地方,SpringBoot的版本控制中心;
以后我们导入依赖是不需要写版本;但是如果导入的包没有在依赖中管理就需要手动导入配置版本。
启动器:spring-boot-starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
spring-boot-starter-xxx : 表示spring-boot的场景启动器
spring-boot-starer-web: 帮我们导入了web模块正常运行所依赖的组件;
SpringBoot将所有的功能场景都抽取出来,做成一个个的starer(启动器),只需要在项目中引入这些starter即可,所有相关的依赖都会导入进来,我们要用什么功能就导入什么样的场景启动器即可;我们未来也可以自己定义staretr;
主启动类
分析完了pom.xml文件现在我们来看看这个启动类
默认的主启动类
// @SpringBootApplication : 标注这个类是一个springboot的应用
@SpringBootApplication
public class HelloSpringBoot {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(HelloSpringBoot.class, args);
}
}
但是这个类一点都不简单! 让我们继续来分析
@SpringBootApplication
作用:标注某个类上表示这个类是SpringBoot的主要配置类,SpringBoot就应该运用这个类的main方法来启动springboot应用;
进入这个注解:可以看到上面还有其他注解!‘
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
@AliasFor(
annotation = EnableAutoConfiguration.class
)
Class<?>[] exclude() default {};
@ComponentScan
这个注解在Spring中很重要,它对应XML配置中的元素。
作用:自动扫描并加载符合条件的组件或者bean,将这个bean定义到IOC容器中
@SpringBootConfiguration
作用:springboot的配置类,标注在某个类上,表示一个SpringBoot的配置类;
我们继续进入这个注解查看
//我们点击@Configuration注解得到下面的@Component
@Configuration
@Component
这里的@Configuration,说明这是一个配置类,配置类就是对spring的xml配置文件;
里面的@Component这说明,启动类本身也是spring中的组件而已,负责启动应用。
我们回到@SpringBootConfiguration注解中继续看。
@EnableAutoConfiguration
@EnableAutoConfiguration:开启自动配置功能
以前我们需要自己配置的东西,而现在springboot可以自动帮我们配置;
@EnableAutoConfiguration告诉springboot开启自动装配配置功能,作用自动装配才能生效。
点进注解继续查看:
@AutoConfigurationPackage :自动装配包
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
@Import:spring底层注解@import,给容器中导入一个组件
Registrar.class 作用:将主启动类的所有包及包下所有子包里面的所有组件扫描spring容器;
我们继续退回上一步,
@Import({AutoConfigurationPackages.Registrar.class}):给容器导入组件;
AutoConfigurationImportSelector :自动配置导入选择器,那么它会导入那些组件的选择器 我们点击进去看这个类的源码:
1、这个类中有一个这样的方法
// 获得候选的配置
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
//这里的getSpringFactoriesLoaderFactoryClass()方法
//返回的就是我们最开始看的启动自动导入配置文件的注解类;EnableAutoConfiguration
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
2、这个方法又调用了 SpringFactoriesLoader类的静态方法!我们进入SpringFactoriesLoader类loadFactoryNames() 方法
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
return forDefaultResourceLocation(classLoader).loadFactoryNames(factoryType);
}
3、发现一个多次出现的文件:spring.factories,全局搜索它
spring.factories
我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源所在!
我们在上面的自动配置类随便找一个打开看看,比如 :WebMvcAutoConfiguration
这些一个个的都是JavaConfig配置类,而且都注入了一些bean可以找一下自己认识的类,熟悉一下!
所有,自动装配真正实现是从classpath中搜索所有META-INF/spring.factories配置文件,并将其中对应的rg.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类,然后将这些都汇总成一个实例化并加载到IOC容器中。
自动配置的流程图
结论
1、springboot在启动的时候从类路径的META-INF/spring.factories中获取EnableAutoConfiguation指定的值
2、将这些值作为自动配置类导入容器,自动配置类就生效,帮我们进行自动配置工作;
3、整个JAVAEE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;
4、它会給容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件;
5、有了自动装配类,免去了我们手动编写配置注入功能组件等的工作;
springApplication
这是一个不简单的方法
刚刚开始我还以为只是一个简单的main方法,没想到却开启了一个服务器;
@SpringBootApplication
public class HelloSpringBoot {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(HelloSpringBoot.class, args);
}
}
SpringApplication.run分析
分析该方法主要分为两部,一是SpringApplication的实列化,二是run方法的执行;
SpringApplication
这个类主要做了以下四件事情:
- 推断应用的类型是普通项目还是web项目
- 查找并加载所有初始化器,设置到initiaizers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
查看构造器:
public class SpringApplication {
public static final String BANNER_LOCATION_PROPERTY_VALUE = "banner.txt";
public static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";
private static final String SYSTEM_PROPERTY_JAVA_AWT_HEADLESS = "java.awt.headless";
private static final Log logger = LogFactory.getLog(SpringApplication.class);
static final SpringApplicationShutdownHook shutdownHook = new SpringApplicationShutdownHook();
private static final ThreadLocal<SpringApplicationHook> applicationHook = new ThreadLocal();
}
run方法流程分析图
ic final SpringApplicationShutdownHook shutdownHook = new SpringApplicationShutdownHook();
private static final ThreadLocal applicationHook = new ThreadLocal();
}
## run方法流程分析图
[外链图片转存中...(img-I8JOEOsU-1685159325246)]
=========大家可以自己根据图来理解一下=========