SpringBoot自定义Starter指南
SpringBoot的Starter自动配置机制极大地简化了依赖管理和应用配置,使得开发者可以以最少的配置快速启动和运行Spring应用。
有时,标准的Starter可能无法满足特定需求,这时我们可以创建自定义Starter来扩展SpringBoot的功能。
什么是SpringBoot Starter
SpringBoot Starter是一个特殊的依赖描述符,它包含了一系列的库依赖,这些库依赖定义了某个功能领域(如web应用、数据库访问等)所需的所有类库。SpringBoot通过spring-boot-autoconfigure
模块提供的自动配置机制来自动配置这些依赖。
Web应用开发
- spring-boot-starter-web:用于创建Web应用和RESTful服务,包含Tomcat和Spring MVC。
- spring-boot-starter-webflux:用于构建响应式Web应用,基于Reactor和Spring WebFlux。
数据库访问
- spring-boot-starter-data-jpa:集成Spring Data JPA和Hibernate,用于关系数据库的操作。
- spring-boot-starter-data-mongodb:用于与MongoDB数据库的集成。
- spring-boot-starter-data-redis:用于与Redis键值存储的集成。
库依赖
把具备某些功能的坐标打包到一起,简化依赖导入。
比如导入了spring-boot-starter-web
这个starter,那么和web相关的jar包都一起自动导入到项目中了。
自动配置
无需手动配置xml,由starter进行自动配置并管理bean,简化开发过程。
以mybatis-spring-boot-starter
为例。
1)当引入了mybatis-spring-boot-starter
后,其引入的相关依赖如下:
2)它导入了一个mybatis-spring-boot-autoconfigure
的jar包,其中有一个自动配置类MybatisAutoConfiguration
。
3)打开看看,里面的关键代码
4)其中@Configuration
和@Bean
注解,结合使用替代传统的xml配置文件,把SqlSessionTemplate
和SqlSessionFactory
注入到Spring容器。
注解@EnableConfigurationProperties
,其作用是让后面指定的配置属性MybatisProperties
类生效。
把此类标记为一个配置属性类,prefix指定了前缀,其属性就是配置的可选参数。
如配置包的别名:mybatis.type-aliases-package=com.yyh.entity
。
5)那么这个MybatisAutoConfiguration
类是怎么被加载的呢?
在META-INF/spring.factories
文件中,定义了MybatisAutoConfiguration
。
当 SpringBoot 应用程序启动时,会去加载该 jar 包下的META-INF/spring.factories
文件。
详情可以参考:SpringBoot自动装配原理解析
命名规范
spring-boot-starter-xxx
是SpringBoot官方定义的jar,如 spring-bbot-starter-web。
xxx-spring-boot-starter
是非官网定义的,如第三方jar包 mybatis-spring-boot-starter。
自定义 Starter
一般来说,需要我们自定义 starter 的原因如下:
- 封装功能:封装一组特定的功能,使其可以轻松地在其他项目中复用。
- 简化配置:自动配置相关类库,减少重复的配置工作。
- 模块化设计:保持应用的模块化,将特定功能隔离在单独的模块中。
比如,我们现在要新建一个 token-redis-spring-boot-starter
。
1)新建项目,配置 pom。
2)在包util下创建类TokenProperties
,此类是一个配置属性类。
3)在包service下创建类TokenService,作为一个服务。
4)在包config下创建类TokenAutoConfiguration
,实现自动配置,把服务注入到Spring中。
5)创建 spring.factories文件
#后面的路径是TokenAutoConfiguration所在的路径
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.config.TokenAutoConfiguration
6)把项目打包发布到 maven 仓库。
7)新建一个项目,并引入token-redis-spring-boot-starter
。
8)在配置文件中配置
9)测试运行
输出:127.0.0.1,0000,8888888
条件注解
在文中出现了好几个类似于这样的注解@ConditionalXXX
。
比如:@ConditionalOnProperty
、@ConditionalOnClass
、 @ConditionalOnMissingBean
@Conditional
是在 SpringFramework 4.0 版本正式推出的,它可以让 Bean的装载基于一些指定的条件,换句话说,被标注@Conditional
注解的 Bean 要注册到 IOC 容器时,必须全部满足@Conditional
上指定的所有条件才可以。
@ConditionalOnProperty
@ConditionalOnProperty
注解用于根据配置文件中的属性值来决定是否加载某个自动配置类。
- 属性名称:可以指定一个或多个属性名称,只有当这些属性被设置时,自动配置类才会被加载。
- 属性值:可以进一步指定需要匹配的属性值,只有当属性的值与指定值相匹配时,自动配置类才会被加载。
@Configuration
@EnableConfigurationProperties({TokenProperties.class})
@ConditionalOnProperty(
value = {"token.enabled"},
havingValue = "true"
)
public class TokenAutoConfiguration {
public TokenAutoConfiguration() {
}
@Bean
public TokenService tokenService() {
return new TokenService();
}
}
在这个例子中,只有当配置文件中存在token.enabled
属性,TokenAutoConfiguration
类才会被加载。
@ConditionalOnClass
@ConditionalOnClass
注解用于检查类路径上是否存在某个类,如果存在,则加载自动配置类。
- classes:指定一个或多个类,如果这些类在类路径上被找到,自动配置类就会被加载。
@Configuration
@ConditionalOnClass(name = {"com.mysql.cj.jdbc.Driver"})
public class MySqlAutoConfiguration {
// ...
}
在这个例子中,只有当类路径上存在com.mysql.cj.jdbc.Driver
类时,MySqlAutoConfiguration
类才会被加载,这通常意味着MySQL JDBC驱动已经添加到了项目的依赖中。
@ConditionalOnMissingBean
@ConditionalOnMissingBean
注解用于检查Spring容器中是否已经存在某个特定的Bean,如果不存在,则创建一个新的Bean。
- value:指定需要检查的Bean的类型。
- search:指定搜索Bean的范围,默认为SearchStrategy.ALL,意味着在当前上下文和父上下文中搜索。
@Configuration
public class MyServiceAutoConfiguration {
@Bean
@ConditionalOnMissingBean(MyService.class)
public MyService myService() {
return new DefaultMyService();
}
}
在这个例子中,如果Spring容器中没有MyService类型的Bean,那么myService方法将被调用以创建一个新的MyService Bean。
组合使用条件注解
这些条件注解可以单独使用,也可以组合使用,以满足更复杂的条件判断需求。
例如,可以同时使用@ConditionalOnProperty
和@ConditionalOnClass
来确保某个自动配置类只在满足特定属性值和类路径上有特定类时才被加载。
@Configuration
@ConditionalOnProperty(name = "myapp.enabled")
@ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
public class MySqlAutoConfiguration {
// ...
}
在这个例子中,MySqlAutoConfiguration
只有在配置文件中设置了myapp.enabled
属性,并且类路径上存在com.mysql.cj.jdbc.Driver
类时才会被加载。