中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

深入 Spring Boot:編寫兼容 Spring Boot1 和 Spring Boot2 的 Starter

2018-07-30    來源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

前言

Spring Boot 2正式發(fā)布已經(jīng)有段時(shí)間,應(yīng)用升級(jí)之前,starter先要升級(jí),那么如何支持Spring Boot 2?

為什么選擇starter同時(shí)兼容spring boot 1和spring boot 2

從用戶角度來看

如果不在一個(gè)starter里兼容,比如用版本號(hào)來區(qū)分,spring boot 1的用戶使用1.*,spring boot 2用戶使用2.*,這樣用戶升級(jí)會(huì)有很大困擾。

另外,我們的starter是以日期為版本號(hào)的,如果再分化,則就會(huì)出現(xiàn)2018-06-stable-boot1,2018-06-stable-boot2,這樣子很丑陋。

從開發(fā)者角度來看

要同時(shí)維護(hù)兩個(gè)分支,修改代碼時(shí)要合到兩個(gè)分支上,發(fā)版本時(shí)要同時(shí)兩個(gè)。如果有統(tǒng)一的bom文件,也需要維護(hù)兩份。工作量翻倍,而且很容易出錯(cuò)。

因此,我們決定在同一個(gè)代碼分支里,同時(shí)支持spring boot 1/2。減少開發(fā)維護(hù)成本,減少用戶使用困擾。

編寫兼容的starter的難點(diǎn)

spring boot starter的代碼入口都是在各種@Configuration類里,這為我們編寫兼容starter提供了條件。

但還是有一些難點(diǎn):

  • 某些類不兼容,比如在spring boot 2里刪除掉了
  • 代碼模塊,maven依賴怎樣組織
  • 怎樣保證starter在spring boot 1/2里都能正常工作

通過ASM分析現(xiàn)有的starter里不兼容的類

  • https://github.com/hengyunabc/springboot-classchecker

springboot-classchecker可以從jar包里掃描出哪些類在spring boot 2里不存在的。

工作原理:springboot-classchecker自身在pom.xml里依賴的是spring boot 2,掃描jar包里通過ASM分析到所有的String,提取出類名之后,再嘗試在ClassLoader里加載,如果加載不到,則說明這個(gè)類在spring boot 2里不存在。

例如掃描demo-springboot1-starter.jar?:

mvn clean package
java -jar target/classchecker-0.0.1-SNAPSHOT.jar demo-springboot1-starter.jar

結(jié)果是:

path: demo-springboot1-starter.jar
org.springframework.boot.actuate.autoconfigure.ConditionalOnEnabledHealthIndicator
org.springframework.boot.actuate.autoconfigure.EndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.HealthIndicatorAutoConfiguration

那么這些類在spring boot 2在哪里了?

實(shí)際上是改了package:

org.springframework.boot.actuate.autoconfigure.health.ConditionalOnEnabledHealthIndicator
org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration
org.springframework.boot.actuate.autoconfigure.health.HealthIndicatorAutoConfiguration

通過掃描20多個(gè)starter jar包,發(fā)現(xiàn)不兼容的類有:

  • org.springframework.boot.env.PropertySourcesLoader
  • org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder
  • org.springframework.boot.bind.RelaxedDataBinder
  • Endpoint/HealthIndicator 相關(guān)的類

可以總結(jié):

  • spring boot核心的類,autoconfigure相關(guān)的沒有改動(dòng)
  • 大部分修改的是Endpoint/HealthIndicator 相關(guān)的類

spring-boot-utils兼容工具類

  • https://github.com/hengyunabc/spring-boot-utils

spring-boot-utils提供兼容工具類,同時(shí)支持spring boot 1/2。

BinderUtils

在spring boot 1里,注入環(huán)境變量有時(shí)需要用到RelaxedDataBinder

MyProperties myProperties = new MyProperties();
MutablePropertySources propertySources = environment.getPropertySources();
new RelaxedDataBinder(myProperties, "spring.my").bind(new PropertySourcesPropertyValues(propertySources));

在spring boot 2里,RelaxedDataBinder刪除掉了,新的寫法是用Binder

Binder binder = Binder.get(environment);
MyProperties myProperties = binder.bind("spring.my", MyProperties.class).get();

通過BinderUtils,則可以同時(shí)支持spring boot1/2:

MyProperties myProperties = BinderUtils.bind(environment, "spring.my", MyProperties.class);

@ConditionalOnSpringBoot1/@ConditionalOnSpringBoot2

spring boot starter的功能大部分都是通過@Configuration組裝起來的。spring boot 1的Configuration類,不能在spring boot 2里啟用。則可以通過@ConditionalOnSpringBoot1@ConditionalOnSpringBoot2這兩個(gè)注解來分別支持。

其實(shí)原理很簡(jiǎn)單,判斷spring boot 1/2里各自有的存在的類就可以了。

@ConditionalOnClass(name = "org.springframework.boot.bind.RelaxedDataBinder")
public @interface ConditionalOnSpringBoot1 {
}
@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder")
public @interface ConditionalOnSpringBoot2 {
}

Starter代碼模塊組織

下面以實(shí)際的一個(gè)starter來說明。

  • https://github.com/hengyunabc/endpoints-spring-boot-starter

spring boot web應(yīng)用的mappings信息,可以在/mappings?endpoint查詢到。但是這么多endpoint,它們都提供了哪些url?

endpoints-spring-boot-starter的功能是展示所有endpoints的url mappings信息

endpoints-spring-boot-starter里需要給spring boot 1/2同時(shí)提供endpoint功能,代碼模塊如下:

endpoints-spring-boot-starter
|__ endpoints-spring-boot-autoconfigure1
|__ endpoints-spring-boot-autoconfigure2
  • endpoints-spring-boot-autoconfigure1模塊在pom.xml里依賴的是spring boot 1相關(guān)的jar,并且都設(shè)置為<optional>true</optional>
  • endpoints-spring-boot-autoconfigure2的配置類似
  • endpoints-spring-boot-starter依賴autoconfigure1 和 autoconfigure2
  • 如果有公共的邏輯,可以增加一個(gè)commons模塊

Endpoint兼容

以 endpoints-spring-boot-autoconfigure1模塊為例說明怎樣處理。

EndPointsEndPoint類繼承自spring boot 1的AbstractMvcEndpoint

@ConfigurationProperties("endpoints.endpoints")
public class EndPointsEndPoint extends AbstractMvcEndpoint {

通過@ManagementContextConfiguration引入

@ManagementContextConfiguration
public class EndPointsEndPointManagementContextConfiguration {

    @Bean
    @ConditionalOnMissingBean
    @ConditionalOnEnabledEndpoint("endpoints")
    public EndPointsEndPoint EndPointsEndPoint() {
        EndPointsEndPoint endPointsEndPoint = new EndPointsEndPoint();
        return endPointsEndPoint;
    }

}

在META-INF/resources/spring.factories里配置

org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration=\
io.github.hengyunabc.endpoints.autoconfigure1.EndPointsEndPointManagementContextConfiguration

因?yàn)?code>org.springframework.boot.actuate.autoconfigure.ManagementContextConfiguration是只在spring boot 1里,在spring boot 2的應(yīng)用里不會(huì)加載它,所以autoconfigure1模塊天然兼容spring boot 2。

那么類似的,autoconfigure2模塊里在META-INF/resources/spring.factories配置的是

org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=\
io.github.hengyunabc.endpoints.autoconfigure2.ManagementApplicationcontextHolderConfiguration

仔細(xì)對(duì)比,可以發(fā)現(xiàn)是spring boot 2下面修改了ManagementContextConfiguration的包名,所以對(duì)于Endpoint天然是兼容的,不同的模塊自己編繹就可以了。

HealthIndicator的兼容

類似Endpoint的處理,spring boot 1/2的代碼分別放不同的autoconfigure模塊里,然后各自的@Configuration類分別使用@ConditionalOnSpringBoot1/@ConditionalOnSpringBoot2來判斷。

通過集成測(cè)試保證兼容性

還是以endpoints-spring-boot-autoconfigure1模塊為例。

這個(gè)模塊是為spring boot 1準(zhǔn)備的,則它的集成測(cè)試要配置為spring boot 2。

參考相關(guān)的代碼:查看

  • springboot2demo/pom.xml里依賴spring boot 2
  • verify.groovy里檢測(cè)應(yīng)用是否啟動(dòng)成功

總結(jié)

  • 通過ASM分析現(xiàn)有的starter里不兼容的類
  • 配置注入通過BinderUtils解決
  • 各自的@Configuration類分別用@ConditionalOnSpringBoot1/@ConditionalOnSpringBoot2來判斷
  • 代碼分模塊:commons放公共邏輯, autoconfigure1/autoconfigure2 對(duì)應(yīng) spring boot 1/2的自動(dòng)裝配,starter給應(yīng)用依賴
  • Endpoint的Configuration入口是ManagementContextConfiguration,因?yàn)閟pring boot 2里修改了package,所以直接在spring.factories里配置即可
  • 通過集成測(cè)試保證兼容性
  • 如果某一天,不再需要支持spring boot 1了,則直接把a(bǔ)utoconfigure1模塊去掉即可

鏈接

  • https://github.com/hengyunabc/spring-boot-utils
  • https://github.com/hengyunabc/springboot-classchecker
  • https://github.com/hengyunabc/endpoints-spring-boot-starter

標(biāo)簽: isp ssl 代碼 開發(fā)者

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:Spring Security 5.0.7 發(fā)布,Spring 安全框架

下一篇:SQL Server 與 MySQL 中排序規(guī)則與字符集相關(guān)知識(shí)的一點(diǎn)總結(jié)