1.前言
我們用spring boot發(fā)現(xiàn)會有很多spring-boot-starter-xxx,在實際開發(fā)中可能會通過@Bean注解來實現(xiàn)組件的加載,我們希望通過配置文件如application.yml或者application.properties來實現(xiàn)自定義類的加載到spring 容器中去。
本文采用spring boot版本為2.1.1為例。
官方文檔建議我們自定義組件命名最好采用xxx-spring-boot-starter 命名規(guī)則參考。
2.準備知識
| 知識點 | 學習網(wǎng)址 | 特性 |
|---|---|---|
| @Configuration | 配置元數(shù)據(jù) | spring 3.0開始 引入該注解, @Configuration作用 在用于描述類、 接口(包括注解類型) 或enum聲明。 初始化配置類我們知道有2種方式: 1.通過META-INF/ spring.factories文件來實現(xiàn) org.springframework.boot .autoconfigure.EnableAuto Configuration = \com.even.fastjson. FastJsonAutoConfiguration (spring boot采用SPI的約定)。 2.采用掃包的方式 scanBasePackages實現(xiàn)。 |
| @EnableConfiguration Properties |
注冊的屬性類 | 該注解是用來開啟對 @ConfigurationProperties注解配置Bean的支持。 也就是@EnableConfiguration Properties注解 告訴Spring Boot 能支持@ConfigurationProperties。 |
| @ConditionalOnClass | 條件注解 | 含義是有某個類bean才會加載。 |
| @ConditionalOnProperty | @Conditional OnProperty 來控制Configuration 是否生效 |
通過其兩個屬性name以及havingValue來實現(xiàn)的,其中name用來從application.properties中讀取某個屬性值。 如果該值為空,則返回false;如果值不為空,則將該值與havingValue指定的值進行比較,如果一樣則返回true;否則返回false。 如果返回值為false,則該configuration不生效;為true則生效。 |
| @Conditional OnWebApplication |
Web應用程序條件 | 讓配置取決于 應用程序是否是一個“Web應用程序”被包括在內(nèi)。 Web應用程序是使用 Spring WebApplicationContext, 定義session范圍或具有的任何應用程序StandardServletEnvironment。 |
| fastJson | fastJson | FastJson是一個Java庫,可用于將Java對象轉(zhuǎn)換為其JSON表示。 它還可用于將JSON字符串轉(zhuǎn)換為等效的Java對象。 FastJson可以處理任意Java對象,包括您沒有源代碼的預先存在的對象。 |
3.依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fast.json}</version>
</dependency>
4.代碼實現(xiàn)
1.創(chuàng)建FastJsonProperties類,主要是放默認的fastJson配置文件。
@ConditionalOnClass({JSON.class})
@ConfigurationProperties(prefix = "spring.fastjson")
public class FastJsonProperties {
/**
* 默認Content-Type
*/
private final static String DEFAULT_MEDIA_TYPE = "application/json;charset=UTF-8";
/**
* 是否生效
*/
private boolean enabled;
/**
* 默認List<MediaType>
*/
private List<MediaType> supportedMediaTypes = MediaType.parseMediaTypes(DEFAULT_MEDIA_TYPE);
/**
* 實例化一個FastJsonConfig對象
*/
private FastJsonConfig config = new FastJsonConfig();
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<MediaType> getSupportedMediaTypes() {
return supportedMediaTypes;
}
public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes) {
this.supportedMediaTypes = supportedMediaTypes;
}
public FastJsonConfig getConfig() {
return config;
}
public void setConfig(FastJsonConfig config) {
this.config = config;
}
2.創(chuàng)建FastJsonAutoConfiguration類。
- (1)注入配置文件類。
- (2)過濾配置文件值判斷是否生效。
- (3)重新構(gòu)造HttpMessageConverter方法。
- (4)把bean注入到容器中。
@Configuration
@EnableConfigurationProperties({FastJsonProperties.class})
@ConditionalOnClass({JSON.class, HttpMessageConverter.class})
public class FastJsonAutoConfiguration {
@Resource
private FastJsonProperties fastJsonProperties;
@Bean
@ConditionalOnProperty(prefix = "spring.fastjson", name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnWebApplication
public HttpMessageConverter<?> httpMessageConverter() {
/**
* FastJsonHttpMessageConverter轉(zhuǎn)換類
*/
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
/*媒體類型*/
fastJsonHttpMessageConverter.setSupportedMediaTypes(fastJsonProperties.getSupportedMediaTypes());
/*配置*/
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonProperties.getConfig());
return fastJsonHttpMessageConverter;
}
3.在resources下的META-INF里創(chuàng)建spring.factories文件,spring boot通個這個文件來掃包把我們的bean加載到容器中
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.even.fastjson.FastJsonAutoConfiguration
4.為了讓IDE編輯器能提示我們一些配置提示我們自己創(chuàng)建一個spring-configuration-metadata.json文件里面添加一些元數(shù)據(jù)。
參考文檔
{
"properties": [
{
"name": "spring.fastjson.supportedMediaTypes",
"type": "java.lang.String",
"description": "Description for spring.fastjson.supportedMediaTypes.",
"defaultValue": "application/json;charset=UTF-8"
},
{
"name": "spring.fastjson.config.serializerFeatures",
"type": "com.alibaba.fastjson.serializer.SerializerFeature",
"description": "Description for spring.fastjson.config.serializerFeatures."
},
{
"name": "spring.fastjson.enabled",
"type": "java.lang.Boolean",
"description": "Whether to enable FastJsonHttpMessageConverter.",
"defaultValue": true
},
{
"name": "spring.fastjson.config.dateFormat",
"type": "java.lang.String",
"description": "Date serialization format."
}
],
"hints": [
{
"name": "spring.fastjson.supportedMediaTypes",
"values": [
{
"value": "application/json;charset=UTF-8"
},
{
"value": "text/html"
},
{
"value": "text/plain"
},
{
"value": "text/xml"
}
]
},
{
"name": "spring.fastjson.config.serializerFeatures",
"providers": [
{
"name": "handle-as",
"parameters": {
"target": "com.alibaba.fastjson.serializer.SerializerFeature"
}
}
]
},
{
"name": "spring.fastjson.enabled",
"values": [
{
"value": true
},
{
"value": false
}
]
},
{
"name": "spring.fastjson.config.dateFormat",
"values": [
{
"value": "yyyy-MM-dd"
},
{
"value": "yyyy-MM-dd HH:mm:ss"
},
{
"value": "HH:mm:ss"
}
]
}
]
}
6.自定義starter代碼完成了需要打成jar包,別的spring-boot只需要將這個包引用進來。
注意打包的時候看一下target/classes/META-INF/下是否有spring.factories文件,我打包的時候出現(xiàn)了沒有這個文件導致我測試fastjson一直不生效。
7.測試
- (1)創(chuàng)建一個新的spring-boot項目。
- (2)引入spring-boot-fastjson-starter包。
- (3)在配置文件開啟spring.fastjson.enabled=true。
- (4)寫一個demo這里就省略demo。
User類
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@Builder
public class User {
//去掉ID
@JSONField(serialize=false)
private Long id;
@JSONField(ordinal = 3)
private String name;
private int age;
@JSONField(ordinal = 1)
private LocalDate birthday;
}
(5)輸出結(jié)果:{"age":20,"birthday":"2018-12-21","name":"even"}
5.資料
- 參考文檔:spring-boot文檔
- 參考源碼:fastjson-spring-boot-starter
- 筆者源碼地址:spring-boot-fastjson-starter
- 筆者測試demo源碼地址:spring-boot-fastjson
- 筆者郵箱:even366@qq.com