成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

利用Spring的Conditional注解來(lái)實(shí)現(xiàn)FeatureToggle

FreeZinG / 3810人閱讀

摘要:最近一個(gè)使用的項(xiàng)目中需要進(jìn)行性能調(diào)優(yōu)。是不允許進(jìn)入進(jìn)行操作的。如上的寫法表示和是啟用的。從開(kāi)始提供的注解。最后啟用這兩個(gè)在項(xiàng)目啟動(dòng)入口小結(jié)通過(guò)上述幾步,在項(xiàng)目啟動(dòng)時(shí)通過(guò)注解的條件判斷,實(shí)現(xiàn)不同的裝配,從而啟用不同的。

最近一個(gè)使用Spring的項(xiàng)目中需要進(jìn)行性能調(diào)優(yōu)。方式基本上是編寫新的代碼實(shí)現(xiàn)原來(lái)一樣的業(yè)務(wù)邏輯,只是實(shí)現(xiàn)方式有一些調(diào)整,例如增加cache,優(yōu)化算法等等。

一開(kāi)始大家希望直接在原有代碼基礎(chǔ)上修改,但是這樣一來(lái),就要跟上每周一次的發(fā)布節(jié)奏,一周搞定難度太大。于是決定拷貝出的package來(lái)重構(gòu)。在沒(méi)啟用之前這個(gè)package下都是dead code。這樣做的好處有幾點(diǎn):

在調(diào)優(yōu)后的code啟用前,業(yè)務(wù)至少不會(huì)受影響。

利用docker的特性,可以實(shí)現(xiàn)灰度發(fā)布,比如啟動(dòng)兩個(gè)docker,一個(gè)是老的code,一個(gè)啟用新的code,利用nginx實(shí)現(xiàn)分流。

灰度發(fā)布后發(fā)現(xiàn)有緊急bug,只需要devOps修改一點(diǎn)配置,重啟docker可以再切回老的code。

出發(fā)點(diǎn)

既然要實(shí)現(xiàn)上述第三點(diǎn),也就是利用配置來(lái)實(shí)現(xiàn)切換,那么這個(gè)Enable的flag就不應(yīng)該寫到代碼里,甚至是配置文件里,因?yàn)轫?xiàng)目啟動(dòng)都是在docker中通過(guò)spring-boot的cmd直接啟動(dòng)的。DevOps是不允許進(jìn)入docker進(jìn)行操作的。

實(shí)現(xiàn)

想到我們的整個(gè)部署架構(gòu)是基于Kubernetes的,可以通過(guò)修改工程的deployment.yaml文件來(lái)實(shí)現(xiàn)。原理就是deployment里面設(shè)置一個(gè)docker的Env,Key是FeatureToggle,Value可以是這樣FeatureA,FeatureB ,當(dāng)docker啟動(dòng)時(shí),JVM(Java代碼)可以通過(guò)System.getenv()來(lái)獲得環(huán)境變量,從來(lái)知道這個(gè)Feature是需要啟用還是不啟用。如上的寫法表示FeatureA和FeatureB是啟用的。

我們可以寫一個(gè)簡(jiǎn)單的接口實(shí)現(xiàn)來(lái)判斷:

public boolean isFeatureEnable(String featureName) {
    // 用System.getenv("FeatureToggle")讀取環(huán)境變量判斷是否包含參數(shù)的featureName
    // ...
}
進(jìn)一步使用

雖然我們有了判斷方法,但是因?yàn)轫?xiàng)目組的人都有潔癖,我們不希望代碼中到處都是

if(isFeatureEnable(featureA)) {
    // new code
} else {
    // old code
}

這樣實(shí)在是太ugly了。

我們需要利用spring的IoC特性來(lái)切換implementations。Spring從4.0開(kāi)始提供Conditional的注解。結(jié)合@Configuration就可以實(shí)現(xiàn)app啟動(dòng)時(shí)的不同Bean的注入。

寫一個(gè)FeatureA的Condition Class

public class FeatureACondition implements Condition{
 
  @Override
  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    return isFeatureEnable("featureA")
  }
}

再寫一個(gè)Spring的Configuration來(lái)使用這個(gè)Condition

@Configuration
@Conditional(FeatureACondition.class)
public class FeatureAConfiguration {
 
  @Bean(name="bizService")
  public BizService bizService(){
      return new EnhancedBizService();
  }
 
}

當(dāng)然如果要實(shí)現(xiàn)互斥的切換,即啟用FeatureA另一個(gè)Bean就不能加載的話,那么再寫一個(gè)NotFeatureA的Configuration就可以了。

@Configuration
@Conditional(NotFeatureACondition.class)
public class NotFeatureAConfiguration {
 
  @Bean(name="bizService")
  public BizService bizService(){
      return new OldBizService();
  }
 
}

這樣一來(lái),當(dāng)FeatureA啟用時(shí)BizService這個(gè)interface的實(shí)現(xiàn)就是EnhancedBizService,反之它的實(shí)現(xiàn)就是OldBizService。
當(dāng)然你在configuration上用@ComponentScan,@Import等等都是沒(méi)問(wèn)題的,在啟動(dòng)時(shí)都會(huì)最先判斷Conditional,如果不滿足spring根本不會(huì)繼續(xù)下面的掃描或者加載操作。

最后啟用這兩個(gè)Config
在項(xiàng)目啟動(dòng)入口

@SpringBootApplication
@Import({NotFeatureAConfiguration.class, FeatureAConfiguration.class})
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
小結(jié)

通過(guò)上述幾步,在spring項(xiàng)目啟動(dòng)時(shí)通過(guò)conditional注解的條件判斷,實(shí)現(xiàn)不同Bean的裝配,從而啟用不同的Feature。
對(duì)于Devops而言,只需要在deployment里面修改Env的內(nèi)容,再重啟deploy這個(gè)app就可以實(shí)現(xiàn)Feature Toggle了。即使你不使用Kubernetes,docker-compose也是一樣的道理。
通過(guò)修改docker-compose.yml實(shí)現(xiàn):

environment:
  - FeatureToggle=FeatureA,FeatureB
  - SESSION_SECRET

總而言之就是充分利用OO語(yǔ)言的優(yōu)勢(shì),實(shí)現(xiàn)可拔插的FeatureToggle。接下來(lái)我們還會(huì)繼續(xù)研究如何Runtime的啟用Feature,我也發(fā)現(xiàn)了一個(gè)已有的輪子togglz。如果有朋友用過(guò),歡迎反饋使用感受。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/65246.html

相關(guān)文章

  • 追蹤解析Spring ioc啟動(dòng)源碼(2)

    摘要:顧名思義,其主要作用是解析標(biāo)簽。本例中沒(méi)有用到上述的注解,所以均為。繼續(xù)追蹤這行代碼的內(nèi)部實(shí)現(xiàn)獲取的名稱調(diào)用的方法注冊(cè)過(guò)程見(jiàn)處理的別名,本例中沒(méi)有別名,不進(jìn)入循環(huán)的具體內(nèi)容有待研究,不展開(kāi)。到此為止,已經(jīng)被注冊(cè)到中。 接上篇 3 reader 注冊(cè)配置類 該 part 的起點(diǎn): public AnnotationConfigApplicationContext(Class... ann...

    funnyZhang 評(píng)論0 收藏0
  • 2.走向自動(dòng)裝配

    摘要:走向自動(dòng)裝配模式注解裝配走向自動(dòng)裝配課程介紹手動(dòng)裝配自動(dòng)裝配自動(dòng)裝配是以手動(dòng)裝配為基礎(chǔ)實(shí)現(xiàn)的手動(dòng)裝配模式注解模式注解是一種用于聲明在應(yīng)用中扮演組件角色的注解。 2.走向自動(dòng)裝配 Spring 模式注解裝配 2-1 走向自動(dòng)裝配 課程介紹 spring framework手動(dòng)裝配 spring boot自動(dòng)裝配 spring boot自動(dòng)裝配是以spring framework手動(dòng)裝...

    rose 評(píng)論0 收藏0
  • Spring注解專題系列

    摘要:用法先創(chuàng)建個(gè)組件,,,分別在類上加上注解。發(fā)現(xiàn)有一個(gè)屬性源碼注釋這樣說(shuō)的自動(dòng)檢測(cè)使用組件。在的方法中,表示不匹配,代表匹配。這就說(shuō)明使用注冊(cè)組件有種方式。 Spring注解應(yīng)用篇--IOC容器Bean組件注冊(cè) 這是Spring注解專題系類文章,本系類文章適合Spring入門者或者原理入門者,小編會(huì)在本系類文章下進(jìn)行企業(yè)級(jí)應(yīng)用實(shí)戰(zhàn)講解以及spring源碼跟進(jìn)。 環(huán)境準(zhǔn)備 編譯器IDEA...

    CocoaChina 評(píng)論0 收藏0
  • 這樣講 SpringBoot 自動(dòng)配置原理,你應(yīng)該能明白了吧

    摘要:這里有一個(gè)參數(shù),主要是用來(lái)指定該配置項(xiàng)在配置文件中的前綴。創(chuàng)建一個(gè)配置類,里面沒(méi)有顯式聲明任何的,然后將剛才創(chuàng)建的導(dǎo)入。創(chuàng)建實(shí)現(xiàn)類,返回的全類名。創(chuàng)建實(shí)現(xiàn)類,實(shí)現(xiàn)方法直接手動(dòng)注冊(cè)一個(gè)名叫的到容器中。前言 小伙伴們是否想起曾經(jīng)被 SSM 整合支配的恐懼?相信很多小伙伴都是有過(guò)這樣的經(jīng)歷的,一大堆配置問(wèn)題,各種排除掃描,導(dǎo)入一個(gè)新的依賴又得添加新的配置。自從有了 SpringBoot 之后,咋...

    cc17 評(píng)論0 收藏0
  • Spring Boot中那些條件判斷

    摘要:通過(guò)操作系統(tǒng)進(jìn)行條件判斷,從而進(jìn)行配置。分別對(duì)布爾,字符串和數(shù)字三種類型進(jìn)行判斷。通過(guò)指定的資源文件是否存在進(jìn)行條件判斷,比如判斷來(lái)決定是否自動(dòng)裝配組件。判斷當(dāng)前環(huán)境是否是應(yīng)用。 Spring Boot中的那些Conditional spring boot中為我們提供了豐富的Conditional來(lái)讓我們得以非常方便的在項(xiàng)目中向容器中添加Bean。本文主要是對(duì)各個(gè)注解進(jìn)行解釋并輔以代碼...

    Nekron 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<