1. 自动配置流程
- 导入
starter
- 依赖导入
autoconfigure
- 寻找类路径下
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件 - 启动,加载所有
自动配置类
xxxAutoConfiguration
- 给容器中配置功能
组件
组件参数
绑定到属性类
中。xxxProperties
属性类
和配置文件
前缀项绑定@Contional
派生的条件注解进行判断是否组件生效
所有场景自动配置好可以直接使用,修改配置文件,就会修改底层参数,例如:通过修改yaml
配置server.port
,就可以修改tomcat运行端口,注入SpringBoot配置好的组件可以随时使用。
2. SPI机制
- Java中的SPI(Service Provider Interface)是一种软件设计模式,用于在应用程序中动态地发现和加载组件 。SPI的思想是,定义一个接口或抽象类,然后通过在classpath中定义实现该接口的类来实现对组件的动态发现和加载。
SPI的主要目的是解决在应用程序中使用 可插拔组件 的问题。例如,一个应用程序可能需要使用不同的日志框架或数据库连接池,但是这些组件的选择可能取决于运行时的条件。通过使用SPI,应用程序可以在运行时发现并加载适当的组件,而无需在代码中硬编码这些组件的实现类。
在Java中,SPI的实现方式是通过在META-INF/services目录下创建一个以服务接口全限定名为名字的文件,文件中包含实现该服务接口的类的全限定名。当应用程序启动时,Java的SPI机制会自动扫描classpath中的这些文件,并根据文件中指定的类名来加载实现类。
通过使用SPI,应用程序可以实现更灵活、可扩展的架构,同时也可以避免硬编码依赖关系和增加代码的可维护性。
在SpringBoot中,文件位置位于:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
场景:抽取聊天机器人场景,它可以打招呼.
效果:任何项目导入此
starter
都具有打招呼功能,并且问候语中的人名需要可以在配置文件中修改
- 创建自定义starter项目,引入spring-boot-starter基础依赖
- 编写模块功能,引入模块所有需要的依赖。
- 编写
xxxAutoConfiguration
自动配置类,帮其他项目导入这个模块需要的所有组件 - 编写配置文件
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
指定启动需要加载的自动配置 - 其他项目引入即可使用
3. @EnableXxxx 功能开关
自动配置,项目一启动,SPI文件中指定的所有类都会加载。通过@EnableXxxx
手动控制哪些功能的开启; 手动导入。都是利用 @Import
把此功能要用的组件导入进去。
4. SpringBoot核心注解
1. @SpringBootApplication
@SpringBootConfiguration
就是: @Configuration
,容器中的组件,配置类。spring ioc启动就会加载创建这个类对象
@EnableAutoConfiguration
:开启自动配置
开启自动配置
@AutoConfigurationPackage
:扫描主程序包:加载自己的组件
- 利用
@Import(AutoConfigurationPackages.Registrar.class)
想要给容器中导入组件。 - 把主程序所在的包的所有组件导入进来。
@Import(AutoConfigurationImportSelector.class)
:加载所有自动配置类:加载starter导入的组件
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()) .getCandidates(); Assert.notEmpty(configurations, "No auto configuration classes found in " + "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
扫描SPI文件:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@ComponentScan
组件扫描:排除一些组件(哪些不要)
排除前面已经扫描进来的配置类、和自动配置类。
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
2. 完整启动加载流程
5. 自定义starter
1. 创建robot-boot-starter模块
这个模块作为公有的聊天机器人模块,也就是有很多项目模块都需要引入它
引入依赖
<parent> <artifactId>spring-boot-starter-parent</artifactId> <groupId>org.springframework.boot</groupId> <version>3.0.5</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> <scope>provided</scope> </dependency> <!-- 导入配置处理器,配置文件自定义的properties配置都会有提示--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> </dependencies>
自定义配置有提示。导入以下依赖重启项目,再写配置文件就有提示
@ConfigurationProperties(prefix = "robot", ignoreInvalidFields = true) //此属性类和配置文件指定前缀绑定 @Component @Data public class RobotProperties { private String name; }
<!-- 导入配置处理器,配置文件自定义的properties配置都会有提示--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
@Service public class RobotService { @Autowired private RobotProperties robotProperties; public String hello(){ return "你好," + robotProperties.getName(); } }
2. 创建spring-user模块
引入聊天机器人模块(
robot-boot-starter
)
<dependency> <groupId>org.robot</groupId> <artifactId>robot-boot-starter</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
@RequestMapping(value = "/user") @RestController public class UserController { //这个组件是在robot-boot-starter模块中定义的 @Autowired private RobotController robotController; public String robot(){ return robotController.hello(); } }
yml配置
robot: name: chatgpt
6. 如何在业务模块中实现公有模块中的组件注册
方式一(指定包扫描)
Spring默认只扫描启动类目录下和子包下边的组件,所以这里要指定扫描robot-boot-starter
包
@ComponentScan(value = {"org.robot"}) //扫描机器人模块下的组件 @SpringBootApplication public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }
方式二(XxxAutoConfiguration)
在robot-boot-starter
模块写一个RobotAutoConfiguration
,给容器中导入这个场景需要的所有组件
@Import({RobotController.class, RobotProperties.class, RobotService.class}) public class RobotAutoConfiguration { }
在spring-user
模块中,导入RobotAutoConfiguration.class
@Import(RobotAutoConfiguration.class) @SpringBootApplication public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }
方式三(@EnableXxx)
使用
@EnableXxx
机制,只要使用这个注解 就会开启这个功能
在robot-boot-starter
模块自定义@EnableRobot
注解
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented //以上元注解直接找个@EnableXxx类 拷贝进来即可 @Import(RobotAutoConfiguration.class) public @interface EnableRobot { }
在spring-user
模块中启用注解,相当于导入了RobotAutoConfiguration.class
中导入的组件
@EnableRobot @SpringBootApplication public class UserApplication { public static void main(String[] args) { SpringApplication.run(UserApplication.class, args); } }
别人引入starter
需要使用 @EnableRobot
开启功能,灵活配置
方式四(完全自动配置)
- 依赖SpringBoot的SPI机制
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件中编写好我们自动配置类的全类名即可- 项目启动,自动加载我们的自动配置类
在
robot-boot-starter
类路径下新建META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
,里边放入指定要扫描的配置类
org.robot.config.RobotAutoConfiguration
这样只要别的项目引入了robot-boot-starter
模块,里边的组件都会自动注入