SpringBoot3 automatic configuration process SPI mechanism core annotation custom starter

1. Automatic configuration process

  1. importstarter
  2. dependency importautoconfigure
  3. META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsFind files in the classpath
  4. start, load all自动配置类 xxxAutoConfiguration
    1. Configure functions in the container组件
    2. 组件参数bound to 属性类.xxxProperties
    3. 属性类Bind with 配置文件the prefix item
    4. @ContionalDerived conditional annotations to judge whether the component is valid

All scenarios are automatically configured and can be used directly. Modifying the configuration file will modify the underlying parameters. For example, by modifying the configuration, the yamltomcat server.portrunning port can be modified, and the components configured by SpringBoot can be injected and used at any time.

2. SPI mechanism

  • SPI ( Service Provider Interface) in Java is a software design pattern for dynamically discovering and loading components in applications . The idea of ​​SPI is to define an interface or abstract class, and then realize the dynamic discovery and loading of components by defining the class that implements the interface in the classpath. The main purpose of SPI is to solve the problem of using pluggable components
    in applications . For example, an application may need to use a different logging framework or database connection pool, but the choice of these components may depend on runtime conditions. By using SPI, applications can discover and load appropriate components at runtime without hardcoding the implementation classes of these components in the code. In Java, SPI is implemented by creating a file with the fully qualified name of the service interface in the META-INF/services directory, which contains the fully qualified name of the class that implements the service interface. When the application starts, Java's SPI mechanism will automatically scan these files in the classpath, and load the implementation class according to the class name specified in the file. By using SPI, applications can achieve a more flexible and extensible architecture, while also avoiding hard-coded dependencies and increasing code maintainability.

In SpringBoot, the file location is at:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

Scene: Extract the chatbot scene, it can say hello.
Effect: Any project imported into this starterhas the function of greeting, and the name of the person in the greeting needs to be modified in the configuration file

  1. Create a custom starter project and introduce spring-boot-starter basic dependencies
  2. Write the module function and import all the required dependencies of the module.
  3. Write xxxAutoConfigurationan automatic configuration class to help other projects import all the components required by this module
  4. Write a configuration file META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsto specify the automatic configuration that needs to be loaded at startup
  5. Other projects can be imported and used

3. @EnableXxxx function switch

Automatic configuration, when the project starts, all classes specified in the SPI file will be loaded. By @EnableXxxxmanually controlling which functions are turned on; manual import. All use to @Importimport the components to be used for this function.

4. SpringBoot core annotations

1. @SpringBootApplication

@SpringBootConfiguration

That is: @Configuration, the components in the container, the configuration class. When spring ioc starts, it will load and create this class object

@EnableAutoConfiguration: Turn on automatic configuration

Turn on automatic configuration

@AutoConfigurationPackage:scan main package :load own components

  • Use @Import(AutoConfigurationPackages.Registrar.class)wants to import components into the container.
  • Import all components of the package where the main program is located.

@Import(AutoConfigurationImportSelector.class): load all auto-configuration classes: load components imported by 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;
	}

Scan SPI files:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@ComponentScan

Component scanning: Exclude some components (which ones do not)
exclude configuration classes that have been scanned in before, and automatic configuration classes.

@ComponentScan(excludeFilters = {
    
     @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

2. Complete bootloading process

insert image description here

5. Custom starter

1. Create the robot-boot-starter module

This module is a public chat robot module, that is, many project modules need to import it

Introduce dependencies

<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>

There are hints for custom configuration. Import the following dependencies to restart the project, and then write the configuration file and there will be a prompt

@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. Create spring-user module

Import chatbot module ( 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 configuration

robot:
  name: chatgpt

6. How to realize the component registration in the public module in the business module

Method 1 (designated package scanning)

By default, Spring only scans the components under the startup class directory and sub-packages, so here you need to specify the scan robot-boot-starterpackage

@ComponentScan(value = {
    
    "org.robot"}) //扫描机器人模块下的组件
@SpringBootApplication
public class UserApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(UserApplication.class, args);
    }
}

Method 2 (XxxAutoConfiguration)

robot-boot-starterWrite one in the module RobotAutoConfigurationand import all the components needed for this scene into the container

@Import({
    
    RobotController.class, RobotProperties.class, RobotService.class})
public class RobotAutoConfiguration {
    
    
}

In spring-usera module, importRobotAutoConfiguration.class

@Import(RobotAutoConfiguration.class)
@SpringBootApplication
public class UserApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(UserApplication.class, args);
    }
}

Method 3 (@EnableXxx)

Using @EnableXxxthe mechanism, as long as you use this annotation, this function will be enabled

robot-boot-starterCustom @EnableRobotannotations in modules

@Retention(RetentionPolicy.RUNTIME)
@Target({
    
    ElementType.TYPE})
@Documented
//以上元注解直接找个@EnableXxx类 拷贝进来即可
@Import(RobotAutoConfiguration.class)
public @interface EnableRobot {
    
    

}

spring-userEnable annotations in the module, which is equivalent to importing the RobotAutoConfiguration.classcomponents imported in

@EnableRobot
@SpringBootApplication
public class UserApplication {
    
    

    public static void main(String[] args) {
    
    
        SpringApplication.run(UserApplication.class, args);
    }
}

Others starterneed to use @EnableRobotthe enable function for introduction, flexible configuration

Method 4 (fully automatic configuration)

  • Rely on SpringBoot's SPI mechanism
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importsJust write the full class name of our automatic configuration class in the file
  • The project starts and automatically loads our automatic configuration class

Create a new one under robot-boot-starterthe class path META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports, and put the configuration class specified to be scanned inside

org.robot.config.RobotAutoConfiguration

In this way, as long as other projects import robot-boot-startermodules, the components inside will be automatically injected

Guess you like

Origin blog.csdn.net/weixin_43847283/article/details/131876708