一、什么是Starter
Starter是Spring Boot 中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境进行自动装配。使用者只需要依赖响应功能的Starter,无需做过多的配置和依赖,SpringBoot就能自动扫描并加载响应的模块。
例如:spring-boot-starter-web 就能使得项目支出Spring MVC,并且SpringBoot还为我们做了很多默认配置,无需再依赖spring-web、spring-webmvc等相关包。
SpringBoot存在很多开箱即用的Starter依赖,使得我们在开发业务代码时能够非常方便的,不需要过多关注框架的配置,而只需要关注业务
二、Starter编写
其实Starter本质与普通的Maven工程没有太大的区别。
本demo主要是简单梳理一下思路,选择的内容也比较简单根据需要选择注入来达到内容格式化的效果。所需要的依赖:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.2.5.RELEASE</version>
<optional>true</optional>
</dependency>
1.定义一个格式化接口
public interface FormatProcessor {
//定义一个格式化的方法
<T> String format(T obj);
}
JSON格式化:
public class JsonFormat implements FormatProcessor{
@Override
public <T> String format(T obj) {
return "JsonFormatProcessor:"+ JSON.toJSONString(obj);
}
}
字符串格式化:
public class StringFormat implements FormatProcessor{
@Override
public <T> String format(T obj) {
return "StringFormatProcessor:"+ Objects.toString(obj);
}
}
进行注入:
@Configuration
public class FormatAutoConfiguration {
@ConditionalOnMissingClass(value = "com.alibaba.fastjson.JSON") //如果没有这个类的时候 注入
@Bean
@Primary //优先级较高的装载
public FormatProcessor stringFormat(){
return new StringFormat();
}
@ConditionalOnClass(name = "com.alibaba.fastjson.JSON") //有的话注入这个
@Bean
public FormatProcessor jsonFormat(){
return new JsonFormat();
}
}
配置文件的编写:
@ConfigurationProperties(prefix = HelloProperties.HELLO_FORMAT_PREFIX)
public class HelloProperties {
//配置前缀
public static final String HELLO_FORMAT_PREFIX = "com.ccc.format";
//存储配置信息
private Map<String,Object> info;
public Map<String, Object> getInfo() {
return info;
}
public void setInfo(Map<String, Object> info) {
this.info = info;
}
}
编写Properties配置文件并且指定配置前缀,那么这个有什么用呢?
我们SpringBoot项目中,通常会有一个applicaiton.properties/yml文件来进行配置。举个最简单的例子你输入一个server他会出现server.port配置,你输入spring.datasource会出现很多关于数据库的配置。那么这些功能就是由此代码来实现的。待会会举例。
注入配置文件:
@Configuration
@EnableConfigurationProperties(HelloProperties.class)
@Import(FormatAutoConfiguration.class)
public class HelloAutoConfiguration {
@Bean
public HelloFormatTemplate helloFormatTemplate(FormatProcessor formatProcessor,HelloProperties properties){
return new HelloFormatTemplate(formatProcessor,properties);
}
}
编写一个模板方法:
public class HelloFormatTemplate {
private FormatProcessor formatProcessor;
private HelloProperties helloProperties;
public HelloFormatTemplate(FormatProcessor formatProcessor,HelloProperties helloProperties) {
this.formatProcessor = formatProcessor;
this.helloProperties = helloProperties;
}
/**
* 简单写一段输出语句来区分两种格式化
*/
public <T> String doFormat(T obj){
StringBuilder builder = new StringBuilder();
builder.append("begin : Execute format"). append("<br/>");
builder.append("HelloProperties:").append(formatProcessor.format(helloProperties.getInfo())).append("<br/>");
builder.append("Obj format result :").append(formatProcessor.format(obj)).append("\n");
return builder.toString();
}
}
对于这个方法应该都不会陌生,类似于常用到的redisTemplate和restTemplate。
到这里一个简单的Starter就完成了。下面进行打包,并复制pom中项目地址
三、测试
在另外新建一个SpringBoot项目 引入上面依赖。
<dependency>
<groupId>com.ccc.starter</groupId>
<artifactId>format-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
在配置文件中输入:com.ccc就会出现提示
简单写几个信息
@RestController
public class FormatController {
@Autowired
HelloFormatTemplate helloFormatTemplate;
@GetMapping("format")
public String format(){
//随便建个实体类
User user = new User();
user.setAge(18);
user.setName("张三");
return helloFormatTemplate.doFormat(user);
}
}
启动测试:
发现启动报错了,失败原因很简单,注入失败了。
原因是在我们引入依赖的时候SpringBoot并没有扫描到所以无法注入。如何解决呢?
在我们的Starter工程中的resouces下新建META-INF文件夹,并新建一个spring.factories文件并写入主动注入配置指向我们的配置类。关于这点我在另一篇文章中也大致提到了SpringBoot的自动装配原理,有兴趣的朋友可以看看:分析SpringBoot自动装配原理
org.springframework.boot.autoconfigure.EnableAutoConfiguration =\
com.ccc.starter.autoconfiguration.HelloAutoConfiguration
在进行打包测试。
启动成功。
你会发现在配置文件中信息也能获取到也就达到配置效果了。
那么这里为什么是StringFormat的格式化呢?
因为我们没有在SpringBoot的pom中导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
在测试
StringFormat就变成了JsonFormat。原因是我们在Starter中使用**@ConditionalOnMissingClass和@ConditionalOnClass**进行选择注入。这两个注解简单来说就是一个if-else的关系。
到此,一个简单的Starter就完成了,如果您发现有啥错误的地方,恳请指出批评。在此感谢!