spring @Conditional條件注解以及擴(kuò)展

@Conditional為按照條件配置spring的bean提供了支持,即滿足某種條件下,怎么配置對應(yīng)的bean;

應(yīng)用場景

  • 當(dāng)某一個jar包在classpath中的時候,配置某幾個bean;
  • 當(dāng)某一個bean配置好后,會自動配置一個特定的bean;
  • 當(dāng)某種環(huán)境變量被設(shè)置后,創(chuàng)建某個bean;
  • @Conditional為敏捷開發(fā)所提倡的原則"習(xí)慣優(yōu)于配置"提供了支持;
  • @Conditional是Spring Boot快速開發(fā)框架實現(xiàn)"習(xí)慣優(yōu)于配置"的核心技術(shù);

樣例

我們構(gòu)建一個會議服務(wù)接口屈嗤,其下分別有遠(yuǎn)程會議服務(wù)邑彪,本地會議服務(wù),然后根據(jù)系統(tǒng)運(yùn)行時的環(huán)境信息動態(tài)獲取會議服務(wù)實例執(zhí)行诞帐。

IMeetingService
/**
 * 會議服務(wù)
 */
public interface IMeetingService {

    /**
     * 開會
     * @param cmd
     * @return
     */
     void meeting(String cmd);
}
LocalMeetingServiceImpl
/**
 * 本地會議服務(wù)
 */
public class LocalMeetingServiceImpl implements IMeetingService {
    @Override
    public void meeting(String cmd) {
        System.out.println("this is Local Meeting!");
    }
}
RomteMeetingServiceImpl
/**
 * 遠(yuǎn)程會議服務(wù)
 */
public class RomteMeetingServiceImpl implements IMeetingService {

    @Override
    public void meeting(String cmd) {
        System.out.println("this is Romte Meeting!");
    }
}

實現(xiàn)Conditional注解的執(zhí)行接口:

LocalConditional
public class LocalConditional implements Condition {

    private final static String type = System.getProperty("meeting_type") == null ? "local" :System.getProperty("meeting_type");

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return type.equals("local");
    }
}
RomteConditional
public class RomteConditional implements Condition {
    private final static String type = System.getProperty("meeting_type") == null ? "local" :System.getProperty("meeting_type");

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return type.equalsIgnoreCase("romte");
    }
}

spring Bean配置基于Configuration注解:

MeetingInstanceConfig
@Configuration
public class MeetingInstanceConfig {

    @Bean
    @Conditional(LocalConditional.class)
    public IMeetingService localMeetingService() {
        return new LocalMeetingServiceImpl();
    }

    @Bean
    @Conditional(RomteConditional.class)
    public IMeetingService romteMeetingService() {
        return new RomteMeetingServiceImpl();
    }
}

上面完成了我用例的所有代碼角雷,接下來我們通過main函數(shù)調(diào)用測試:

public static void main( String[] args )
    {
        System.setProperty("meeting_type","romte");
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext("cn.leadeon");
        IMeetingService meetingService = context.getBean(IMeetingService.class);
        meetingService.meeting("開會");
        context.close();
    }

上面用例執(zhí)行結(jié)果為(表明RomteMeetingServiceImpl實現(xiàn)):

this is Romte Meeting!

當(dāng)我們 設(shè)置System.setProperty("meeting_type","locale"); 或者直接注釋掉這行時結(jié)果:

this is Local Meeting!

這樣就通過Conditional注解完成了根據(jù)條件去創(chuàng)建具體的實例祸穷,動態(tài)根據(jù)環(huán)境的信息去實例化服務(wù),達(dá)到服務(wù)智能化創(chuàng)建調(diào)用

springboot條件注解的實現(xiàn)方式

上面的例子提供了兩個Condition分別為RomteConditional與LocalConditional勺三,相對來說比較復(fù)雜雷滚,下面我們按照springboot實現(xiàn)條件判斷注解的思路完善上面樣例:

  1. 定義條件注解Conditional的包裝注解ConditionalOnMeetType
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Conditional(OnMeetTypeCondition.class)
public @interface ConditionalOnMeetType {

    /**
     * 默認(rèn)為local
     *
     * @return
     */
    String value() default "local";
}
  1. 定義條件注解Conditional處理實現(xiàn)類OnMeetTypeCondition
public class OnMeetTypeCondition implements Condition {

    private final static String type =
            System.getProperty("meeting_type") == null ? "local" : System.getProperty("meeting_type");

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //此處根據(jù)方法獲取方法的注解ConditionalOnMeetType傳入的值,根據(jù)值與系統(tǒng)設(shè)置值是否一致判斷吗坚,當(dāng)前方法定義的bean是否注冊到容器中
        if (metadata instanceof MethodMetadata) {
            MethodMetadata methodMetadata = (MethodMetadata) metadata;
            MultiValueMap<String, Object> annMap = methodMetadata
                    .getAllAnnotationAttributes(ConditionalOnMeetType.class.getName());
            String meetType = (String) annMap.getFirst("value");
            return type.equalsIgnoreCase(meetType);
        }
        return false;
    }
}
  1. 定義java配置類以 ConditionalOnMeetType修飾bean
@Configuration
public class MeetingInstanceConfig {

    @Bean
    @ConditionalOnMeetType
    public IMeetingService localMeetingService() {
        return new LocalMeetingServiceImpl();
    }

    @Bean
    @ConditionalOnMeetType("romte")
    public IMeetingService romteMeetingService() {
        return new RomteMeetingServiceImpl();
    }
}

這三步完成了上面樣例的所有功能祈远,springboot的條件注解大多基于這種方式實現(xiàn),簡單清晰商源。
springboot 提供了如下條件注解:

  • ConditionalOnBean
  • ConditionalOnClass
  • ConditionalOnExpression
  • ConditionalOnJava
  • ConditionalOnMissingBean
  • ConditionalOnMissingClass
    等等
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末车份,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子牡彻,更是在濱河造成了極大的恐慌扫沼,老刑警劉巖出爹,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缎除,居然都是意外死亡严就,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門器罐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梢为,“玉大人,你說我怎么就攤上這事轰坊≈” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵肴沫,是天一觀的道長袒炉。 經(jīng)常有香客問我,道長樊零,這世上最難降的妖魔是什么我磁? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮驻襟,結(jié)果婚禮上夺艰,老公的妹妹穿的比我還像新娘。我一直安慰自己沉衣,他們只是感情好郁副,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著豌习,像睡著了一般存谎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肥隆,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天既荚,我揣著相機(jī)與錄音,去河邊找鬼栋艳。 笑死恰聘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吸占。 我是一名探鬼主播晴叨,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼矾屯!你這毒婦竟也來了兼蕊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤件蚕,失蹤者是張志新(化名)和其女友劉穎孙技,沒想到半個月后惧所,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绪杏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纽绍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蕾久。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拌夏,靈堂內(nèi)的尸體忽然破棺而出僧著,到底是詐尸還是另有隱情,我是刑警寧澤障簿,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布盹愚,位于F島的核電站,受9級特大地震影響站故,放射性物質(zhì)發(fā)生泄漏皆怕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一西篓、第九天 我趴在偏房一處隱蔽的房頂上張望愈腾。 院中可真熱鬧,春花似錦岂津、人聲如沸虱黄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橱乱。三九已至,卻和暖如春粱甫,著一層夾襖步出監(jiān)牢的瞬間泳叠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工茶宵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留析二,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓节预,卻偏偏與公主長得像叶摄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子安拟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理蛤吓,服務(wù)發(fā)現(xiàn),斷路器糠赦,智...
    卡卡羅2017閱讀 134,629評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評論 6 342
  • 1.1 spring IoC容器和beans的簡介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器会傲,...
    simoscode閱讀 6,702評論 2 22
  • 有時候锅棕,愛像一株檸檬草,在廣闊的原野上里默默綻放淌山!我愛你裸燎,不需要你知道,不需要你回應(yīng)泼疑,我只將這愛悄悄埋藏在心口深處...
    也許還有我閱讀 211評論 0 0
  • 說起金錢bug德绿,我覺得還挺嚴(yán)重的,還好前段時間已經(jīng)意識到這個嚴(yán)重性退渗,現(xiàn)在慢慢理性的去糾正觀點(diǎn): 1移稳、貪小便宜,看到...
    Connie小明同學(xué)閱讀 139評論 0 0