I. Introduction
Springboot's automatic configuration principle is often asked in interviews, and I can't remember it even after reading it. It is better to write a starter by hand to deepen my memory.
After reading it, I found that most of the starters are based on this principle, and the practice will be memorable.
Core idea: 约定大于配置
.
2. Preliminary study on the principle of starter startup
Let's take a look at how the official website starter
is designed, just write one like this!
We Ctrl
clicked <artifactId>spring-boot-starter-web</artifactId>
to enter the internal pom, and we found that there is a
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
Ctrl
Click here <artifactId>spring-boot-starter</artifactId>
to enter the internal pom of the starter:
we found that this package dependency is what we will do later:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.5.3</version>
<scope>compile</scope>
</dependency>
We can now create two projects:
- spring-boot-starter (starter)
- spring-boot-starter-autoconfigure (automatic configuration package)
The editor saw the reminder written by the official, you can name it according to the official website, don't learn from the editor! !
You should make sure to provide an appropriate namespace for your launcher. Do not start the module name spring-boot with . even if you use a different Maven groupId. We may provide official support for your auto-configured content in the future.
As a rule of thumb, you should name your composite modules after the enabler. For example, suppose you are creating a starter for "acme" and you name the auto-configuration module acme-spring-boot and the starter acme-spring-boot-starter. If you have only one module combining the two, name it acme-spring-boot-starter.
3. Project construction
1. Create a new blank project
Enter the overall project name
and create two new ones in the blank project, which can be created separately here. The editor here is the same as Raytheon, so we will not create separate projects! !
2. Create a new maven project
Package name and name:
3. Create a new springboot project
4. Project structure
Delete all the useless ones here! ! can not delete
4. Configuration
1. Introduce your own autoconfigure dependencies in the starter project
It is the setting of building the project above
<dependencies>
<dependency>
<groupId>com.wang</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
2. spring-boot-autoconfigure pom configuration
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
</dependencies>
Or delete the useless things, the rest is as follows:
Five, write autoconfigure project
1. Configure a bean
First delete the automatic startup class, we don’t need it, create a new bean
in spring-boot-autoconfigure
the project, and don’t need to let this bean be in the container at this time, we write a self-configuration to let it automatically add to the container.
This is the idea of automatic configuration
/**
* 这里不需要让在容器中,我们写一个自己配置,让他自动加入到容器中
* @author wangzhenjun
* @date 2022/10/14 16:26
*/
public class HelloService {
@Autowired
private MyProperties myProperties;
public String HelloWord (String username){
return myProperties.getPrefix() + username + myProperties.getSuffix();
}
}
2. Write a configuration file
Here, in order to obtain the attribute values in the configuration file, most of the springboot automatic configuration source code is written in a configuration file, and others can be obtained according to the beginning 属性和值
! !
/**
* @author wangzhenjun
* @date 2022/10/14 16:28
*/
@Data
@ConfigurationProperties("wang.name")
public class MyProperties {
private String prefix;
private String suffix;
}
3. Write auto-configuration
import com.wang.springbootautoconfigure.properties.MyProperties;
import com.wang.springbootautoconfigure.service.HelloService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author wangzhenjun
* @date 2022/10/14 16:33
*/
@Configuration
//没有这个bean的时候才会生效
@ConditionalOnMissingBean(HelloService.class)
// 加载配置文件,让它成为容器中的bean
@EnableConfigurationProperties(MyProperties.class)
public class ServiceAutoConfiguration {
/**
* 把刚刚写的服务,加入到容器中
*/
@Bean
public HelloService helloService (){
return new HelloService();
}
}
The main thing is condition
to add a few annotations to complete bean
whether to add to the container:
Commonly used:
- @ConditionalOnClass
- @ConditionalOnMissingClass
- @ConditionalOnBean
- @ConditionalOnMissingBean
- @ConditionalOnProperty
4. New spring.factories
We see that the automatic configuration in the source code is to get and load from this file, so we imitate this and create a new one, so that we can scan and add it to the container! !
If it is springboot2.7 or above:
folder name: META-INF.spring
file name:org.springframework.boot.autoconfigure.AutoConfiguration.imports
Just write the full class name in it!
5. Pack
First spring-boot-autoconfigure
package it to the local library, and then package it spring-boot-starter
, the order must be there, otherwise the former package cannot be found! !
6. Test
We are testing a new project, and the editor of the new project will not lead you to build it!
1. Import our starter dependencies
<dependency>
<groupId>com.wang</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
2. Add configuration file
wang:
name:
prefix: hello
suffix: 886
3. Create a new controller test class
@RestController
@RequestMapping("/test")
public class TestController {
@Autowired
private HelloService helloService;
@GetMapping("/starter")
public String starter(){
return helloService.HelloWord("tom");
}
}
4. Test access
The visit was successful, but there are garbled characters in Chinese. I can't find a solution. If you understand, please leave a message to let me know! !
Once the main process is cleared, you can slowly understand the charm of automatic configuration!
The overall process should be like this:
Introduce starter --- xxxAutoConfiguration --- put components in the container ---- bind xxxProperties ---- configuration items
The Chinese is garbled, maybe there is no servlet, if you understand, please leave a message to tell me the solution, thank you! !
7. Summary
Once you see it, you will lose it once you do it! Everyone still has to do their own practice, don't be too high-minded, so that you will gain something, it's just that 约定大于配置+SPI发现机制
!
There are also some annotations that often appear in the source code, you can write the starter yourself after remembering it!