自定义 spring-boot-starter
Spring Boot Java Maven About 5,521 words新建 Spring Boot 项目
添加配置处理器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
更改插件
原插件是打包Spring Boot
应用包的,包含了启动函数,需替换掉。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
更改为apache
的maven
编译插件。
若不更换,依赖了自定义spring-boot-starter
的工程本地能正常运行,但打包时会报:error:(3,47) java: 程序包不存在
。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
属性配置类
自定义spring-boot-starter
中添加配置类,@Data
使用了Lombok
插件。
application.properties
或yml
中配置的属性映射到类字段中。
@Data
@ConfigurationProperties(prefix = "test")
public class TestConfig {
private Integer code;
private String msg;
}
测试服务类
自定义spring-boot-starter
中添加测试服务类,注意:不用加@Service
注解。
public class TestService {
private TestConfig testConfig;
public TestService(TestConfig testConfig) {
this.testConfig = testConfig;
}
public String say() {
return testConfig.getCode() + ":" + testConfig.getMsg();
}
}
自动配置类
属性配置类,在Spring
启动时根据spring.factories
自动加载。
@Configuration
@ConditionalOnClass(TestService.class)
@EnableConfigurationProperties(TestConfig.class)
public class TestAutoConfiguration {
@Autowired
private TestConfig testConfig;
@Bean
@ConditionalOnMissingBean(TestService.class)
public TestService testService() {
return new TestService(testConfig);
}
}
配置文件
在resource
文件夹下新建META-INF
文件夹,在META-INF
文件夹下新建一个名为spring.factories
的文件。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.myspringbootstarter.config.TestAutoConfiguration
编译工程
使用maven
命令行编译,或IDEA
提供的图形化界面。
mvn clean install -DskipTests
使用自定义starter
新建另一个工程, 并依赖刚编译的starter
<dependency>
<groupId>com.example</groupId>
<artifactId>my-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
配置属性
application.properties
配置文件中配置自定义starter
中所需要的属性。
test.code=1
test.msg=This is msg
测试
注入TestService
并打印参数。
@SpringBootApplication
public class MySpringBootStarterTestApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(MySpringBootStarterTestApplication.class, args);
}
@Autowired
private TestService testService;
@Override
public void run(String... args) throws Exception {
String say = testService.say();
System.out.println(say);
}
}
相关注解
@ConditionalOnClass
:只有当指定的class
在classpath
上时,才会被加载;@ConditionalOnMissingBean
:只有当指定的class
没有在classpath
上时,才会被加载;@EnableConfigurationProperties
:开启自动加载指定的配置类;
实现原理
@SpringBootApplication
注解中包含了@EnableAutoConfiguration
,而@EnableAutoConfiguration
注解中又包含了@Import(AutoConfigurationImportSelector.class)
注解。
选择需要加载的配置。
//AutoConfigurationImportSelector类
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
获取自动配置的实体。
//AutoConfigurationImportSelector类
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
getCandidateConfigurations
获取参与的配置。
SpringFactoriesLoader
会从META-INF/spring.factories
中读取对应的工厂信息。
当我们启动项目时,会检查META-INF/spring.factories
中key
为org.springframework.boot.autoconfigure.EnableAutoConfiguration
的值。
//AutoConfigurationImportSelector类
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
相关面试题
问:Spring Boot
项目能以第三方jar包形式给其他工程依赖吗?这个jar
包工程启动类中的@SpringBootApplication
或main
方法需不需要去掉?
答:可以打成依赖类型的jar
包。也不需要去掉启动类等,只需修改maven
插件即可。
代码
https://github.com/fendoudebb/learning/tree/master/java/learn-spring-boot/my-spring-boot-starter
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓