01-总结
SpringBoot自动装配原理
@SpringBootApplication注解是一个复合注解,包含@EnableAutoConfiguration注解,@EnableAutoConfiguration注解中会有@import注解。@import注解解析是在,inoverBeanfactoryPostProcess中解析注解。@import注解引入了AutoConfigurationImportSelector类
AutoConfigurationImportSelector实现DeferredImportSelector接口:又2个比较重要的方法,一个是process() 方法目的是,会获取到META-INF/spring.factories中的配置类,EnableAutoConfiguration然后 @ConditionalOnClass加载配置类。一个是selectImports()会做一些排序,然后统一返回。- DeferredImportSelector接口重写 getImportGroup()
调用 getImportGroup() -> 返回 AutoConfigurationGroup.class ↓ 等Spring 延迟到所有 @Configuration 加载完后: ↓ 创建 AutoConfigurationGroup 实例 ↓ 调用 Group.process() ├── 读取 META-INF/spring.factories ├── 应用 @Conditional 过滤(部分) └── 收集所有配置类到 entries Map ↓ 调用 Group.selectImports() ├── AutoConfigurationSorter 排序 │ ├── @AutoConfigureOrder (数值越小越优先) │ ├── @AutoConfigureBefore (必须在此之前) │ └── @AutoConfigureAfter (必须在此之后) └── 返回排序后的 Entry 列表
SpringBoot内置tomcat的启动原理
- 首先依赖会引入spring-boot-starter-web依赖,引入start的目的自动装配,然后run方法时会创建(AnnotationConfigServletWebServerApplicationContext) 基于WebServer应用启动的ApplicationContext。
- run方法接着往下走会调用refresh方法,在invokeBeanFactoryPostProcessors方法加载自动配置类
- 自动配置类会根据@Condition注解判断加载什么容器的工厂类,比如TomcatServletWebServerFactory,如Tomcat/Jetty/Undertow。
- 会在onRefresh方法中获取WebServerFactory类,比如TomcatServletWebServerFactory创建tomcat。
- 调用WebServerFactory类的getServer方法创建Tomcat类启动tomcat
Springboot如何将DispatcherServlet注册到tomcat的
- 容器启动时,自动配置类 DispatcherServletAutoConfiguration 会把 DispatcherServlet的Bean 注册到容器中,
- 同时也会注册 DispatcherServletRegistrationBean它是一个 ServletRegistrationBean,专门用于向Tomcat注册Servlet
- 在 onRefresh() 启动Tomcat时:
TomcatServletWebServerFactory.getWebServer()创建tomcat后调用 tomcat.addServlet() 注册 DispatcherServlet.
SpringBoot使用外部tomcat的原理
首先设置打包的方式是war包,
第一步:排除内置tomcat;当你引入
spring-boot-starter-web时,它默认传递依赖了spring-boot-starter-tomcat。排除spring-boot-starter-tomcat后,Spring Boot 的 自动配置类(如ServletWebServerFactoryAutoConfiguration)会因为缺少ServletWebServerFactory(Tomcat的实现类)而失效。 此时,你调用的SpringApplication.run()方法会检测到当前环境不是嵌入式Servlet容器,于是它会跳过启动Web服务器的步骤,onrefresh方法是空实现。第二步:外部Tomcat启动时,会根据Servlet规范,通过 SPI(服务提供者接口) 扫描所有JAR包中
META-INF/services/javax.servlet.ServletContainerInitializer文件里注册的类。Spring 提供的SpringServletContainerInitializer就在此列。所以我们直接继承SpringBootServretInitializer类重写configure方法,将Spring的配置类告诉tomcat。tomcat启动时调用onStartup() 方法 → 最终会调用 configure() 方法,加载你的主类配置,调用SpringApplication.run()。比如:去除web.xml配置文件时,Spring 自己就提供了一个类
SpringServletContainerInitializer就实现了ServletContainerInitializer,并标注了@HandlesTypes(WebApplicationInitializer.class),@HandlesTypes注解我要找所有实现了Xxx接口的类,,所以我们也需要写一个WebApplicationInitializerd的实现类,`
SpringBoot的jar能执行的原因有哪些
SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可以执行的jar
这个jar一般称为fat jar,fat jar 包含应用依赖的jar包。
当执行jar -jar 运行的main方法是JarLauncher的main方法,(meta-inf/manifest文件文件中main-class是JarLauncher)。
- 会创建一个类加载器加载BOOT-INF/lib中的jar
- 启动一个新的线程执行应用程序的main方法。
META-INF文件夹中确实有MANIFEST.MF文件,内容如下:
Manifest-Version: 1.0
Spring-Boot-Classpath-Index: BOOT-INF/classpath.idx
Implementation-Title: test
Implementation-Version: 0.0.1-SNAPSHOT
Spring-Boot-Layers-Index: BOOT-INF/layers.idx
Start-Class: top.zouyh.test.TestApplication
Spring-Boot-Classes: BOOT-INF/classes/
Spring-Boot-Lib: BOOT-INF/lib/
Build-Jdk-Spec: 1.8
Spring-Boot-Version: 2.5.13
Created-By: Maven JAR Plugin 3.2.2
Main-Class: org.springframework.boot.loader.JarLauncher配置文件加载顺序
- 通过事件监听的方式读取配置:ConfigApplicationlistener
| 优先级 | 路径 | 说明 |
|---|---|---|
| 1(最高) | ./config/(当前目录下的config子目录) | 常用于生产环境外部化配置 |
| 2 | ./(当前目录) | 部署包同级的配置文件 |
| 3 | classpath:/config/(类路径下的config包) | 开发时常用 |
| 4(最低) | classpath:/(类路径根目录) | 默认位置 |
注解解析顺序
| 顺序 | 阶段 | 执行内容 | 谁触发的 |
|---|---|---|---|
| 1 | BeanFactoryPostProcessor 执行 | 调用所有 BeanFactoryPostProcessor 的 postProcessBeanFactory 方法。 | Spring容器 |
| 1.1 | 第一个执行的 BFP | ConfigurationClassPostProcessor(优先级最高)开始处理配置类。 | 上述调用 |
| 1.1.1 | 处理用户配置 | 解析 @ComponentScan(扫描 @Service、@Controller)、解析 @Import、解析用户写的 @Bean。 | ConfigurationClassPostProcessor |
| 1.1.2 | 处理自动配置 | 解析 spring.factories 或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中的自动配置类。此时才注册自动配置类的 @Bean。 | ConfigurationClassPostProcessor(通过 AutoConfigurationImportSelector) |
| 2 | Bean 实例化 | 根据上述注册的 BeanDefinition 创建单例对象。 | Spring容器 |
- 解析 @ComponentScan → 扫描并注册组件
- 解析 @PropertySource → 加载属性文件
- 解析 @Import
├── 普通类 → 直接注册
├── ImportSelector → 立即执行 selectImports()
├── ImportBeanDefinitionRegistrar → 立即执行 registerBeanDefinitions()
└── DeferredImportSelector → 先收集,最后统一执行 - 解析 @Bean 方法
| 优先级(从高到低) | 实现接口类型 | 典型代表 |
|---|---|---|
| 最高 (第1位) | PriorityOrdered(且是 BeanDefinitionRegistryPostProcessor) | ConfigurationClassPostProcessor |
| 其次 (第2位) | Ordered(且是 BeanDefinitionRegistryPostProcessor) | 某些第三方框架扩展 |
| 再次 (第3位) | 普通 BeanDefinitionRegistryPostProcessor(无排序接口) | 用户自定义的BFP |
| 最后 (第4位) | 普通 BeanFactoryPostProcessor(非Registry子接口) | 用户自定义的普通BFP |