前言
Spring Boot 可以省略众多的繁琐配置,它的众多 starter 可以说是功不可没。例如 Spring Boot 中集成redis,只需要 pom.xml 中引入 spring-boot-starter-data-redis,配置文件中加入s pring.redis.database 等几个关键配置项即可,常用的 starter 还有 spring-boot-starter-web、spring-boot-starter-test、spring-boot-starter-jdbc,相比于传统的 xml 配置可以说是大大减少了集成的工作量。
原理
利用 starter 实现自动化配置只需要两个条件:maven 依赖和配置文件,这里简单介绍下starter 实现自动化配置的流程。
引入 maven 依赖实质上就是导入 jar 包,Spring Boot 项目启动的时候会找到 starter jar 包中的 resources/META-INF/spring.factories 文件,根据 spring.factories 文件中的配置,加载需要自动配置的类,以 mybatis-spring-boot-starter 为例,其自动配置类之一如下:
@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
...
}
对 MybatisAutoConfiguration
中用到的注解的说明:
注解 | 说明 |
---|---|
@Configuration | 表明是一个配置文件,被注解的类将成为一个 Bean 配置类 |
@ConditionalOnClass | 当 classpath 下发现该字节码的情况下进行自动配置 |
@EnableConfigurationProperties | 使 @ConfigurationProperties 注解生效 |
@AutoConfigureAfter | 完成自动配置后实例化这个 Bean |
mybatis-spring-boot-starter 的 pom 文件引用了 mybatis-spring-boot-autoconfigure 依赖,其中的 spring.factories 文件配置如下:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
这样,便可以在 Spring Boot 项目启动的时候会加载 mybatis starter 中的 MybatisLanguageDriverAutoConfiguration
和 MybatisAutoConfiguration
类。
实现
第一步,先实现自定义的 spring-boot-starter;第二步,通过一个 demo 来引入该 starter,测试是否能达到预期的效果。
自定义 Spring Boot Starter
功能
这里讲一下自定义的 Starter 要实现的功能,很简单,提供一个 Service,包含一个能够将字符串加上前后缀的方法 String wrap(String word)
。
Maven 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
这里说下artifactId
的命名问题:Spring 官方 Starter 通常命名为 spring-boot-starter-{name}
,如 spring-boot-starter-web
;非官方 Starter 命名应遵循 {name}-spring-boot-starter
的格式。
属性类
@ConfigurationProperties(value = "example.service")
@Data
public class ExampleProperties {
private String prefix;
private String suffix;
}
用于获取 application 中前缀为 example.service 的配置信息。
Service 类
@Data
@AllArgsConstructor
public class ExampleService {
private String prefix;
private String suffix;
public String wrap(String word) {
return prefix + word + suffix;
}
}
自动配置类
@Configuration
@ConditionalOnClass(ExampleService.class)
@EnableConfigurationProperties(ExampleProperties.class)
public class ExampleAutoConfig {
@Autowired
private ExampleProperties exampleProperties;
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "example.service", value = "enabled", havingValue = "true")
public ExampleService exampleService() {
return new ExampleService(exampleProperties.getPrefix(), exampleProperties.getSuffix());
}
}
@ConditionalOnClass
表示有 ExampleService 类存在时执行。
@EnableConfigurationProperties
表示有 ExampleProperties 类存在时执行。
@ConditionalOnMissingBean
当 ExampleService Bean 缺失时,执行下段代码。
@ConditionalOnProperty
当 example.service.enabled = true
时,执行代码。
spring.factories
在 resources 目录下新建 META_INF 文件夹,并在其中新建 spring.factories,在其中写入:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jake.springboot.starter.config.ExampleAutoConfig
至此,Starter 项目创建完成,使用 mvn install 命令打包。
测试 Starter
引入 Starter 依赖
新建一个 Spring Boot 工程,引入自定义 Starter 依赖。
application 配置
在 application.properties 中配置参数:
example.service.enabled=true
example.service.prefix=####
example.service.suffix=@@@@
测试接口
为方便起见,直接在启动类中直接定义测试接口:
@SpringBootApplication
@RestController
public class StarterTestApplication {
public static void main(String[] args) {
SpringApplication.run(StarterTestApplication.class, args);
}
@Autowired
private ExampleService exampleService;
@GetMapping("wrap")
public String wrap(String word) {
return exampleService.wrap(word);
}
}
启动测试项目,访问:http://localhost:8080/wrap?word=hello
可以得到预期的返回值:###hello@@@
总结
实现自定义 spring-boot-starter 的原理总结如下:
- 创建 spring boot 工程;
- 引入 spring-boot-autoconfigure 依赖;
- 自定义包含核心功能的 Service 等类;
- 自定义自动配置类,将核心功能类中与该装配类绑定,以确保 spring boot 启动时能自动装配;
- 创建 resources/META_INF/spring.factories 文件,在其中写入:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.jake.springboot.starter.config.ExampleAutoConfig
; - mvn install 打包;
- 在其他工程中引用自定义 spring-boot-starter 的依赖。