为什么要自定义starter
实现功能插件热插拔,随用随配置即可。
自定义starter步骤
- 引入对应的依赖
- 编写实现类
- 编写配置文件读取类
- 编写自动装配类
- 编写默认的配置文件
- 在resources/META-INF/spring.factories 中配置我们的自动装配类
具体实现过程
1.pom配置文件
不需要springboot-boot-starter插件,没必要导入其他包。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>helloworld-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>helloworld-spring-boot-starter</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
<!-- 编译命令,在命令行输入以下命令: mvn clean install -Dmaven.test.skip=true-->
2.读取配置文件类
package com.example.helloworldspringbootstarter.properties;/*
*create by test on 2019/12/12
*
*Remark:
*
*/
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "spring.person")
public class PersonProperties {
// 姓名
private String name;
// 年龄
private int age;
// 性别
private String sex = "M";
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getSex() {
return sex;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSex(String sex) {
this.sex = sex;
}
}
3.服务类
package com.example.helloworldspringbootstarter.service;/*
*create by test on 2019/12/12
*
*Remark:
*
*/
import com.example.helloworldspringbootstarter.properties.PersonProperties;
public class PersonService {
private PersonProperties properties;
public PersonService() {
}
public PersonService(PersonProperties properties) {
this.properties = properties;
}
public void sayHello(){
System.out.println("大家好,我叫: " + properties.getName() + ", 今年" + properties.getAge() + "岁"
+ ", 性别: " + properties.getSex());
}
}
4.自动配置类
package com.example.helloworldspringbootstarter.autoconfig;/*
*create by test on 2019/12/12
*
*Remark:
*
*/
import com.example.helloworldspringbootstarter.properties.PersonProperties;
import com.example.helloworldspringbootstarter.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(PersonProperties.class)
@ConditionalOnClass(PersonService.class)
@ConditionalOnProperty(prefix = "spring.person", value = "enabled", matchIfMissing = true)
public class PersonServiceAutoConfiguration {
@Autowired
private PersonProperties properties;
@Bean
@ConditionalOnMissingBean(PersonService.class) // 当容器中没有指定Bean的情况下,自动配置PersonService类
public PersonService personService(){
PersonService personService = new PersonService(properties);
return personService;
}
}
5.手动创建文件夹和文件
src/main/resources/META-INF/spring.factories
文件内容:
#自动配置类的路径
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.helloworldspringbootstarter.autoconfig.PersonServiceAutoConfiguration
6. 当前项目路径下执行:mvn clean install
7.测试,创建新项目,导入starter信息
<dependency>
<groupId>com.example</groupId>
<artifactId>helloworld-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
8.配置application.properties
spring.person.name=helloword
spring.person.age=30
spring.person.sex=WOMAN
9.测试代码
@SpringBootTest
class TestStartarApplicationTests {
@Autowired
private PersonService personService;
@Test
void test(){
personService.sayHello();
}
}
10.结果
Starter原理
- Spring Boot在启动时扫描项目所依赖的JAR包,寻找包含spring.factories文件的JAR包,
- 然后读取spring.factories文件获取配置的自动配置类AutoConfiguration,
- 然后将自动配置类下满足条件(@ConditionalOnXxx)的@Bean放入到Spring容器中(Spring Context)
- 这样使用者就可以直接用来注入,因为该类已经在容器中了
部分注解说明
- @EnableConfigurationProperties(XxxProperties.class) 注解的作用是使@ConfigurationProperties注解生效。如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置文件转化的bean的
- @ConfigurationProperties: 注解主要用来把properties配置文件转化为对应的XxxProperties来使用的,并不会把该类放入到IOC容器中,如果想放入到容器中可以在XxxProperties上使用@Component来标注,也可以使用@EnableConfigurationProperties(XxxProperties.class)统一配置到Application上来,这种方式可以在Application上来统一开启指定的属性,这样也没必要在每个XxxProperties上使用@Component
其他注解可以自己查找
源代码:
https://download.csdn.net/download/u013919153/12028730
本文参考: