如何自定义starter
在springboot启动流程的系列文章中,我们看过了springboot的自动配置机制,本文将基于自动配置机制自定义一个自动配置的starter示例
正文
模块结构
首先,我们准备两个模块service和web,模块结构如
service模块
在service模块中,我们添加一个服务类TestService
public class TestService { public String getName() { return "lay"; } }
接着再添加一个ServiceAutoConfiguration配置类,将TestService变成一个Bean
public class ServiceAutoConfiguration { @Bean public TestService testService() { return new TestService(); } }
还有最重要的一步,将ServiceAutoConfiguration添加到META-INF/spring.factories中成为自动配置类
org.springframework.boot.autoconfigure.EnableAutoConfiguration=cn.lay.service.ServiceAutoConfiguration
这样,service就完毕了,我们看看service模块的结构
web模块
我们先在web的pom.xml文件中添加service的模块依赖
<dependency> <groupId>cn.lay</groupId> <artifactId>service</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
再添加一个TestController
@RestController
public class TestController {
@Autowired
private TestService testService;
@GetMapping("getName")
public String getName() {
return testService.getName();
}
}
启动测试
当我们启动web以后,会根据service的META-INF/spring.factories中配置的自动配置类把TestService变成Bean,然后注入到TestController中
我们打开浏览器测试一下
可以看到,我们成功执行获得结果
添加条件化注解
在META-INF/spring.factories中添加配置类,但是很多时候我们希望配置类在满足一些条件的时候才生效,为此我们可以使用@Conditional注解或者组合了@Conditional注解的注解
本例中,我们将在ServiceAutoConfiguration中使用使用@ConditionalOnClass注解,该注解表示当某个类存在的时候配置类才生效
@ConditionalOnClass(name = "java.lang.String")
public class ServiceAutoConfiguration {
@Bean
public TestService testService() {
return new TestService();
}
}
注解中指明,当String类存在的时候ServiceAutoConfiguration才会进行解析处理,而如果你指明一个不存在的类,如:java.lang.String2,那么TestService将不会被解析成一个Bean
添加properties
我们先在service模块的pom.xml中添加properties处理依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
添加一个配置属性对象
@ConfigurationProperties(prefix = "service") public class ServiceProperties { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "ServiceProperties{" + "name='" + name + '\'' + '}'; } }
在ServiceAutoConfiguration添加为Bean,开启属性自动解析
@ConditionalOnClass(name = "java.lang.String") @EnableConfigurationProperties(value = {ServiceProperties.class}) public class ServiceAutoConfiguration { @Bean public TestService testService() { return new TestService(); } }
把ServiceProperties注入到TestService中
public class TestService { @Autowired private ServiceProperties serviceProperties; public String getName() { return serviceProperties.getName(); } }
回到web模块,在application.properties中添加配置
service.name=lay
重新启动测试,你会看到浏览器获取到了结果
总结
springboot的自动配置,其实就是包了一层自动发现(spi机制)的spring.factories配置,然后通过@Conditional相关的条件化处理来决定是否进行配置类的解析工作。