基于springBoot自动装配,约定大于配置,自定义一个test-spring-boot-starter,在其他项目中引入该starter,会将其自动装配到容器中。
springBoot项目中一般命名为 spring-boot-starter-xxx说明是官方包,例如:spring-boot-starter-web
xxx-spring-boot-starter 一般为非官方的包,例如:druid-spring-boot-starter
主要分为两步:
1.自定义一个名为test-spring-boot-starter的项目,在项目中进行相关配置,使用maven打包,在其他项目中引用该包。
2.在引用的项目中添加相关依赖,并且在配置文件中设置相关属性,就可以达到控制装配Bean的效果。
test-spring-boot-starter是一个可以通过在pom中添加相关依赖,并在配置文件中设置相关属性,达到将对象字符串格式还是JSON格式的效果。
第一步,首先来建一个项目test-spring-boot-starter,在项目中添加相关的依赖。
// JSON格式化
<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>
目录结构如下:
service包
定义一个接口FormatProcessor
public interface FormatProcessor {
<T> String format(T obj);
}
两个实现类JsonFormat,StringFormat
// JsonFormat
public class JsonFormat implements FormatProcessor{
@Override
public <T> String format(T obj) {
return "JsonFormat: "+ JSONObject.toJSONString(obj);
}
}
// StringFormat
public class StringFormat implements FormatProcessor{
@Override
public <T> String format(T obj) {
return "StringFormat: " + obj.toString();
}
}
FormatTemple类
/**
* @author yujiaxing
* @date 2021/10/07
*/
public class FormatTemplate {
private FormatProcessor formatProcessor;
private FormatProperties formatProperties;
public FormatTemplate(FormatProcessor formatProcessor, FormatProperties formatProperties) {
this.formatProcessor = formatProcessor;
this.formatProperties = formatProperties;
}
public <T> String doFormat(T obj){
StringBuilder builder = new StringBuilder();
builder.append("begin : Execute format"). append("<br/>");
builder.append("properties:").append(formatProcessor.format(formatProperties.getInfo())).append("<br/>");
builder.append("format result :").append(formatProcessor.format(obj)).append("\n");
return builder.toString();
}
}
properties包
FormatProperties类
/**
* @author yujiaxing
* @date 2021/10/07
*/
@ConfigurationProperties(prefix = FormatProperties.FORMAT_PROPERTIES_PREFIX)
public class FormatProperties {
public static final String FORMAT_PROPERTIES_PREFIX = "test.format";
public static final String DEFAULT_CHOOSE_STRING = "string";
public static final String DEFAULT_CHOOSE_JSON = "json";
private String choose = DEFAULT_CHOOSE_STRING;
private Map<String, Object> info;
@PostConstruct
private void init(){
info.put("choose",choose);
}
public Map<String, Object> getInfo() {
return info;
}
public void setInfo(Map<String, Object> info) {
this.info = info;
}
public String getChoose() {
return choose;
}
public void setChoose(String choose) {
this.choose = choose;
}
}
config包
OtherConfiguration类
/**
* @author yujiaxing
* @date 2021/10/07
*/
@Configuration
public class OtherConfiguration {
// 没有添加 fashJson 包的时候 注入
@ConditionalOnMissingClass(value = "com.alibaba.fastjson.JSON")
@Bean
@Primary // 优先设置这个
public FormatProcessor stringFormat() {
return new StringFormat();
}
// 添加相应的包,但没有在配置文件中设置 test.format.choose=json,或者配置了 test.format.choose=string
@ConditionalOnClass(name = "com.alibaba.fastjson.JSON")
@ConditionalOnProperty(prefix = "test.format",name = "choose",havingValue = "string",matchIfMissing = true)
@Bean
public FormatProcessor stringFormatV2() {
return new StringFormat();
}
// 添加相应的包,并且在配置文件中设置 test.format.choose=json 才会生效
@ConditionalOnClass(name = "com.alibaba.fastjson.JSON")
@ConditionalOnProperty(prefix = "test.format",name = "choose",havingValue = "json") // 当配置文件中设置 test.format.choose=json 时才会生效,默认为string
@Bean
public FormatProcessor jsonFormat(){
return new JsonFormat();
}
}
FormatConfiguration类
/**
* @author yujiaxing
* @date 2021/10/07
*/
@Configuration
@EnableConfigurationProperties({FormatProperties.class}) // 开启配置属性,可以在配置文件中检索到这个配置文件中的属性,会有提示信息
@Import(OtherConfiguration.class) // 将其他的配置类合并在一起,这样在spring.factories文件中只需要写一个类就好了
public class FormatConfiguration {
@Bean
public FormatTemplate FormatTemplate(FormatProcessor formatProcessor, FormatProperties formatProperties){
return new FormatTemplate(formatProcessor,formatProperties);
}
}
其中EnableConfigurationProperties开启ConfigurationProperties,将ConfigurationProperties作为Bean。
在配置文件中添加属性时,会有提示信息。如下图所示:
最后在resource包下新建META-INF包,添加spring.factories文件。在其中添加自动装配的实现类
# AUTO Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration =\
com.example.starter.config.FormatConfiguration
然后将test-spring-boot-starter打包
新建另一个springBoot项目test-spring-boot-starter-test在项目中引入test-spring-boot-starter依赖
test-spring-boot-starter-test项目结构
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>test-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
主启动类 TestSpringbootStarterTestApplication
@RestController
@SpringBootApplication
public class TestSpringbootStarterTestApplication {
public static void main(String[] args) {
SpringApplication.run(TestSpringbootStarterTestApplication.class, args);
}
@Data
public static class User {
String name;
String sex;
}
@Autowired(required = false)
private FormatTemplate formatTemplate;
@GetMapping("testFormat")
public String doFormat() {
User user = new User();
user.setName("yjx");
user.setSex("MAN");
return formatTemplate.doFormat(user);
}
}
配置文件中设置如下:
test.format.info.author=yjx
test.format.info.time=2021-10-9
启动项目,在浏览器中访问地址 http://localhost:8080/testFormat
结果如下,使用字符串格式化
当在配置文件中设置
test.format.info.author=yjx
test.format.info.time=2021-10-9
test.format.choose=json
重新启动项目,再次访问时,结果如下,使用Json格式化
当把依赖fashJson去掉时,即使设置了test.format.choose=json,也是使用字符串格式化,结果如下
通过springboot的自动装配,将spring.factories文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration的的实现类中定义的Bean注入IOC容器中,并且结合配置文件的形式去控制注入的bean,达到定制化的效果。