Starter主要是在根据条件帮我们做Bean的自动装配。包括包扫描,加载,实例化和注册Bean,提供一种开箱即用的组件。
SpringBoot存在很多
开箱即用的starter依赖,使得我们在开发业务代码的时候非常方便,无需关注框架的配置,只需要关注业务即可。
1、认识starter
Starter是SpringBoot中的一个非常重要概念,
starter
相当于一个模块,它能将模块所需的
依赖jar包-bean 整合起来并对模块内的bean根据条件进行自动配置。使用者只需要依赖相应功能的Starter,无需做过多的配置和依赖,SpringBoot就能自动扫描并加载相应的模块。比如我们使用spring-boot-strter-web就能使项目支持spring-mvc,自动导入加载依赖的spring-web/spring-webmvc等相关包及相关的配置。其
主要功能包括:
-
自动将项目所需要的jar包-Bean自动装载注册到容器Map中;
-
并且提供配置参数的入口及一些默认的参数配置, 遵循约定优于配置的原则;
-
提供一个开箱即用的组件,一个集成化的模块;
2、starter的命名规范
推荐使用以下命名规约;
官方命名空间
-
前缀:spring-boot-starter-{name}
-
模式:spring-boot-starter- 模块名
-
举例:spring-boot-strater-web/spring-boot-starter-actuator/spring-boot-starter-jdbc
自定义命名空间-非官方
-
后缀:{name}-spring-boot-starter
-
模式:模块-spring-boot-starter
-
举例: mybaties-spring-boot-starter
3、自定义starter实践
如果有一些通用的服务接口,工具类,或者自定义的功能性注解,会被很多项目使用,那么我们就可以自己定义一个spring-boot-starter,来简化配置和使用,提高开发效率。
3.1、自定义starter项目模块的划分
以SpringBoot
官方推荐的做法,将starter分为两个模块。
-
starter 启动器 模块:只用来做依赖包的导入:
-
autoconfig模块:专门用来自动配置模块的具体实现;
Starter模块依赖autoconfig模块。使用的时候直接引入starter即可。结构如下:
实例:编写一个用户信息服务组件,功能很简单,就是返回一个用户的信息。
我们目的就是让Starter自动帮我们把这个用户信息组件KingInfoService注入到spring容器中,其他的服务想用的时候就直接引入jar包即可;
第一步:建立
SpringBoot
工程-starter模块;直接引用configuration自动配置jar包即可,其它什么都不用做:
<groupId>com.beijing.starter</groupId>
<artifactId>king-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
<!--启动器-->
<dependencies>
<!--引入自动配置模块-->
<dependency>
<groupId>com.beijing.starter</groupId>
<artifactId>king-spring-boot-starter-autoconfig</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
第二步:建立autoconfig模块:用来做服务的自动装载和配置的具体实现,编写需要自动加载的服务类;
//用户服务组件类
public class KingInfoService {
KingInfoProperties kingInfoProperties;
public KingInfoProperties getKingInfoProperties() {
return kingInfoProperties;
}
public void setKingInfoProperties(KingInfoProperties kingInfoProperties) {
this.kingInfoProperties = kingInfoProperties;
}
//返回一个用户信息,城市和工作时间可配置,只需要传入姓名即可;
public KingInfo getKingInfo(String name ) {
KingInfo kingInfo = new KingInfo();
kingInfo.setName(name);
kingInfo.setPeriod(kingInfoProperties.getPeriod());
kingInfo.setCity(kingInfoProperties.getCity());
return kingInfo;
}
}
用户信息entity类,其中用户信息的工作地点city和工作时间period是可以动态配置:
//用户信息entity类
@Data
public class KingInfo {
private String name;
private Integer period; //属性要求可动态配置
private String city; //属性要求可动态配置
}
第三步:编写用户属性配置元信息类-ConfigurationProperties
思考: 类似于DataSource和Mybaties都有自己的配置参数,那么这些bean配置需要的参数是如何规定并获取的呢?
虽然SpringBoot
帮我们自动导入了需要的jar包,使用了“约定大于配置”的原则给我设定了一些参数的原始值,但是,大多数情况下我们还需要根据自己的环境去改变一些参数的设置,所以这里就需要做到参数可以个性化设置,需要用到属性化配置文件。
//使配置文件可被spring扫描生效,自动配置
@ConfigurationProperties(prefix = KingInfoProperties.KING_PREFIX)
@Data
public class KingInfoProperties {
public static final String KING_PREFIX = "king.info";
private static final String default_name = "king";
private String name = default_name;
private Integer period = 3;
private String city = "beijing";
public KingInfoProperties() {
}
public KingInfoProperties(String name, Integer period,String city) {
this.name = name;
this.period = period;
this.city = city;
}
}
第四步:编写自动装载服务组件配置类-AutoConfiguration;实现服务组件KingInfoService的自动装配,让spring的IOC托管,提供开箱即用功能:
@Configuration //将这个类交给spring托管;
@EnableConfigurationProperties(KingInfoProperties.class) //开启了外部化属性配置
@AutoConfigureAfter(Init.class) //Init.class先加载;
@Import(OtherConfig.class) //导入其他的配置
@ConditionalOnProperty(prefix = KingInfoAutoConfiguration.prefix, value = "enabled", matchIfMissing = true)
public class KingInfoServiceAutoConfiguration {
public static final String prefix = "king.info";
@Autowired //将设置的属性装载进来
private KingInfoProperties kingInfoProperties;
@Bean
@Primary //自动给容器中注入KingInfoService服务组件
@ConditionalOnMissingBean(KingInfo.class)
public KingInfoService kingInfoService() {
KingInfoService kingInfoService = new KingInfoService();
kingInfoService.setKingInfoProperties(kingInfoProperties);
return kingInfoService;
}
}
第五步:配置自动发现配置文件-EnableAutoConfiguration
思考:编写的Bean类是如何让SpringBoot自动扫描和加载到内存的呢?
写完了上面的这些配置类后最重要的是要使这些配置类能被Spring启动的时候自动加载管理,那么这个加载时机是什么时候呢?
SpringFactoriesLoader自动扫描加载
这里用到了SpringFactoriesLoader这个工具类。在SpringBoot的启动原理也有讲到,这里不过多的讲解了。过程主要是:在tomcat启动的时候,会优先去检查寻找classpath/META-INF/spring.factories下需要加载的class类,找到这些类的字节码,然后把它先加载到内存,供后面的服务进行调用。
设置自动装配类的扫描路径key-value的设置。
spring.factories文件的配置, key的值是@EnableAutoConfiguration注解的配置类路径,固定不变;
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.beijing.starter.config.KingInfoServiceAutoConfiguration
整体的目录结构:
至此,我们的starter就已经编写完成了。
第六步:打包发布及使用
编译,安装到仓库,或者发布到私服,其他的服务直接下载引用这个启动器starter—jar包,就可以使用我们用户服务组件了。
<dependency>
<groupId>com.beijing.starter</groupId>
<artifactId>king-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
具体的配置属性city和period我们也可以在appliction.preperties中进行设置,其他的一些starter组件的实现原理和它都是一样的。
4、小结
开发一个自己的spring-boot-starter的具体步骤:具体步骤:
-
建立工程,创建xxx-spring-boot-starter, xxx-spring-boot-autoconfigure模块,导入依赖的第三方jar包;
-
编写属性配置元信息类;
-
编写自动配置类;
-
配置自动发现配置文件:META-INF/spring.factories;
-
打包发布;
参考文件: