自动配置
包扫描规则:
- 默认的扫描规则 @SpringBootApplication 标注的类就是主程序类 ,springBoot也只会扫描主程序类所在的包以及下面的子包
- 也可以自定义声明扫描其他包
- 使用 @SpringBootApplication(scanBasePackages = “com.test”)
- 使用@ ComponentScan( “com.test” ) 来指定包扫描路径
Spring Boot的核心注解是哪个
-
@SpringBootApplication 是 Spring Boot 最核心的注解
-
用在 Spring Boot启动类上,标识这是一个 Spring Boot 应用,用来开启 Spring Boot 的各项能力。
-
这个注解是 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 这三个注解的组合,也可以用这三个注解来代替 @SpringBootApplication 注解。
-
-
@SpringBootConfiguration: 组合了@Configuration 注解,实现配置文件的功能。
-
@EnableAutoConfiguration: 打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能,开启这个注解之后,Spring Boot 就能根据当前类路径下的包或者类来配置 Spring Bean。
-
@ComponentScan: Spring组件扫描,用来代替配置文件中的 component-scan 配置,开启组件扫描,即自动扫描包路径下的 @Component 注解进行注册 bean 实例到 context 中。
-
@Configuration,用来代替 applicationContext.xml 配置文件,所有这个配置文件里面能做到的事情都可以通过这个注解所在类来进行注册。
spring boot的自动配置原理:
-
每一个stater都会导入
spring-boot-starter
,spring-boot-starter
是所有stater的stater,其中又导入了spring-boot-autoconfigure
其中包含了全场景的自动配置类 -
但是spring boot默认只扫描主程序下的包及其子包,所以扫不到
spring-boot-autoconfigure
下写好的配置,只有导入了对应场景的包,相关的配置类才会存在,对应的功能也就生效了 -
spring boot 主程序的注解 @SpringBootApplication 由三个注解组成
-
@SpringBootConfiguration 声明配置类
-
@ComponentScan 扫描指定的组件包
- springboot这里排除了已经加载过的配置类和自动配置类,防止重复加载
-
@EnableAutoConfiguration 是spring boot开启自动配置的核心注解
-
-
最终达到的效果是,导入对应的stater,在配置文件中配置对应的属性值,就能使用对应组件的功能
EnableAutoConfiguration 用于开启自动配置,包含以下注解
-
@AutoConfigurationPackage(加载自己的组件)
- 底层是利用
@Import(AutoConfigurationPackages.Registrar.class)
,把主程序所在的所有组件导入进来,所以springboot默认只扫描主程序所在的包及其子包
- 底层是利用
-
@Import(AutoConfigurationImportSelector.class) (加载springboot提供的组件)
-
用于给容器中批量导入组件,springboot 启动时会自动导入
spring-boot-autoconfigure
包下META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
内默认的配置文件XXXAutoConfiguration
-
虽然会一次性导入很多配置,但是这些配置不一定都生效,是按需生效的,每一个自动配置类都有条件注解,以
RedisAutoConfiguration
为例,想要RedisAutoConfiguration
配置类生效,就必须要有RedisOperations.class
这个类存在
-
@EnableConfigurationProperties({RedisProperties.class})
则会开启这个类和配置文件的绑定,同时RedisProperties定义了配置文件中的前缀(spring.data.redis),这样就可以把配置文件中指定前缀的值绑定到配置类中
-
spring-boot-autoconfigure
其中包含了全场景的自动配置类
按需加载的自动配置
- 每一个stater都会导入
spring-boot-starter
,spring-boot-starter
是所有stater的stater spring-boot-starter
又导入了spring-boot-autoconfigure
其中包含了全场景的自动配置类,但并没有全部开启,只有导入了相关场景才开启对应的配置
SPI机制
- Java中的SPI(Service Provider Interface)是一种软件设计模式,用于在应用程序中动态地发现和加载组件。SPI的思想是,定义一个接口或抽象类,然后通过在classpath中定义实现该接口的类来实现对组件的动态发现和加载。
- SPI的主要目的是解决在应用程序中使用可插拔组件的问题。例如,一个应用程序可能需要使用不同的日志框架或数据库连接池,但是这些组件的选择可能取决于运行时的条件。通过使用SPI,应用程序可以在运行时发现并加载适当的组件,而无需在代码中硬编码这些组件的实现类。
- 在Java中,SPI的实现方式是通过在
META-INF/services
目录下创建一个以服务接口全限定名为名字的文件,文件中包含实现该服务接口的类的全限定名。当应用程序启动时,Java的SPI机制会自动扫描classpath中的这些文件,并根据文件中指定的类名来加载实现类。 - 通过使用SPI,应用程序可以实现更灵活、可扩展的架构,同时也可以避免硬编码依赖关系和增加代码的可维护性。
- SpringBoot的SPL是加载:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
功能开关
-
自动配置:全部都配置好,什么都不用管。 自动批量导入
- 项目一启动,spi文件中指定的所有都加载。
-
@EnableXxxx
:手动控制哪些功能的开启; 手动导入。-
开启xxx功能
-
都是利用 @Import 把此功能要用的组件导入进去
-
Spring Boot 自定义配置
- 使用@PropertySource进行自定义配置
- 如果将所有的配置都集中到 application.properties 或 application.yml 中,那么这个配置文件会十分的臃肿且难以维护,因此可以将与 Spring Boot 无关的配置提取出来,写在一个单独的配置文件中,并在对应的 JavaBean 上使用 @PropertySource 注解指向该配置文件。
- @PropertySource()可以同时支持多个配置文件用逗号隔开
- 使用@ImportResource进行自定义配置
- 可以使用注解@ImportResource 导入spring的配置文件,让配置文件生效。
- 在主启动程序类上使用 @ImportResource 注解,将 Spring 配置文件 beans.xml 加载到项目中
- 使用@Configuration进行自定义配置
- @Configuration用在类上,表示告诉spring这个类是配置类===spring配置文件。
- 配置类内部可以包含有一个或多个被 @Bean 注解的方法,这些方法会被 AnnotationConfigApplicationContext 或 AnnotationConfigWebApplicationContext 类扫描,构建 bean 定义,方法的返回值会以组件的形式添加到容器中,组件的 id 就是方法名。
Springboot:配置文件参数的获取
- 非静态参数,直接使用@Value注解即可获取到参数
- 静态参数,当工具类中的方法需要从配置文件读取参数时,需要将参数定义为静态,才可以在静态方法中获取到,这时候就不能只配置个@Value注解,还要在类上要加@Component注解
生命周期监听器
springboot启动流程
- 在启动类的main方法中,通过调用SpringApplication的静态方法run()来完成整个项目的初始化和启动。
- run方法里主要干了两件事:
- 创建springbootApplication对象
- 创建springbootApplication对象springboot容器初始化操作
- 获取当前应用的启动类型:通过判断当前classpath是否加载servlet类,返回servlet web启动方式。
- webApplicationType三种类型:
- reactive:响应式启动(spring5新特性)
- none:即不嵌入web容器启动(springboot放在外部服务器运行 )
- servlet:基于web容器进行启动
- webApplicationType三种类型:
- 读取springboot下的META-INFO/spring.factories文件,获取对应的ApplicationContextInitializer(初始化器)装配到集合
- 读取springboot下的META-INFO/spring.factories文件,获取对应的 ApplicationListener(初监听器)装配到集合
- 初始化主类mainApplectionClass,定位main方法。
- 并调用实例的run方法,run方法中重点做了以下操作
- 获取监听器和参数配置;
- 打印Banner信息;
- 创建并初始化容器;
- 监听器发送通知。
- 创建springbootApplication对象
生命周期监听器(监听器-SpringApplicationRunListener ),用于监听应用的生命周期,启动过程如下:
监听器的启动过程
-
Listener先要从 META-INF/spring.factories 读到
-
SpringApplicationRunListener下的7个默认方法
- 引导: 利用 BootstrapContext 引导整个项目启动
- starting:应用开始,SpringApplication的run方法一调用,只要有了 BootstrapContext 就执行
- environmentPrepared:环境准备好(把启动参数等绑定到环境变量中),但是ioc还没有创建;【调一次】
- 启动:
- contextPrepared:ioc容器创建并准备好,但是sources 主配置类没加载。并关闭引导上下文;组件都没创建 【调一次】
- contextLoaded:ioc容器加载。主配置类加载进去了。但是ioc容器还没刷新(我们的bean没创建)。
- started:ioc容器刷新了(所有bean造好了),但是 runner 没调用。
- ready :ioc容器刷新了(所有bean造好了),所有 runner 调用完了。
- failed:如果应用启动失败(starting之后,running之前),会执行的逻辑
- 引导: 利用 BootstrapContext 引导整个项目启动
-
运行:以前步骤都正确执行,代表容器running(context.isRunning())。
自定义SpringApplicationRunListener来监听事件:
-
编写SpringApplicationRunListener 实现类,用来监听spring的声明周期
-
在 META-INF/spring.factories 中配置 org.springframework.boot.SpringApplicationRunListener=自己的Listener,还可以指定一个有参构造器,接受两个参数(SpringApplication application, String[] args)
-
springboot 在spring-boot.jar中配置了默认的 Listener,配置文件的写法为:
org.springframework.boot.SpringApplicationRunListener=\ com.psh.Listener.MyApplicationRunListener
事件驱动开发
应用启动过程生命周期事件感知(9大事件)**、**应用运行中事件感知(无数种)。
- 事件发布:
ApplicationEventPublisherAware
或注入:ApplicationEventMulticaster
- 事件监听:
组件 + @EventListener
事件驱动的开发的好处:
- 如果在原本的登录功能上,需要新增新的服务,原本的开发方式需要修改登录接口
- 而事件驱动的开发,不需要修改原本的代码,可以直接新增服务,监听登录事件,这样就做到了只新增,不修改(对扩展开放,对修改关闭)
场景如下:
- 事件发布者发部事件,事件订阅者监听事件
- 当事件发生时,监听这个事件的订阅者,可以自动执行某些逻辑
@Order(0)
可以用来指定监听的顺序的,数组越小,优先级越高,默认的事件顺序是按照事件监听器名字的首字母排序的
自定义stater
自定义stater步骤
- 创建
自定义starter
项目,引入spring-boot-starter
基础依赖 - 编写模块功能,引入模块所有需要的依赖。
- 编写
xxxAutoConfiguration
自动配置类,帮其他项目导入这个模块需要的所有组件 - 编写配置文件
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
指定启动需要加载的自动配置 - 其他项目引入即可使用
自定义配置可以在配置文件中有提示
<!--导入配置处理器,配置文件自定义的properties配置都会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
自定义stater不需要启动类,抽取完业务代码后,编写一个自动配置类,导入需要的组件,因为springBoot默认只会导入主程序及其子包下的组件,所以需要手动导入
@Configuration
//导入容器中要用到的所有组件
@Import({CustomConfig.class, CustomController.class, CustomServiceImpl.class})
public class CustomAutoConfiguration {
}
然后再编写配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
指定启动需要加载的自动配置类
其他项目直接引用自定义的stater,并且再配置文件中写入对应的配置,就能有对应的功能