最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Spring?@Profile注解的使用和源碼解析

 更新時(shí)間:2023年04月14日 10:07:03   作者:劉牌  
這篇文章主要將通過源碼帶大家深入了解一下Spring中@Profile注解的原理與使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

介紹

在之前的文章中,寫了一篇使用Spring @Profile實(shí)現(xiàn)開發(fā)環(huán)境,測試環(huán)境,生產(chǎn)環(huán)境的切換,之前的文章是使用SpringBoot項(xiàng)目搭建,實(shí)現(xiàn)了不同環(huán)境數(shù)據(jù)源的切換,在我們實(shí)際開發(fā)中,會(huì)分為dev,test,prod等環(huán)境,他們之間數(shù)獨(dú)立的,今天進(jìn)來詳解介紹Spring @Profile的原理。

Spring注解@Profile實(shí)現(xiàn)開發(fā)環(huán)境,測試環(huán)境,生產(chǎn)環(huán)境的切換

使用

帶有@Profile的注解的bean的不會(huì)被注冊進(jìn)IOC容器,需要為其設(shè)置環(huán)境變量激活,才能注冊進(jìn)IOC容器,如下通過setActiveProfiles設(shè)置了dev值,那么這三個(gè)值所對應(yīng)的Bean會(huì)被注冊進(jìn)IOC容器。當(dāng)然,我們在實(shí)際使用中,不會(huì)這樣去做,使用SpringBoot的話,我們一般是使用yml,在yml中配置spring.profiles.active,也可以通過配置jvm參數(shù)。

通過Environment設(shè)置profile

我們可以直接通過Environment來設(shè)置環(huán)境屬性,這是比較原生的方法。

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");

通過JVM參數(shù)設(shè)置

可以通過JVM參數(shù)來設(shè)置環(huán)境變量的值,在開發(fā)中,這種方式也是使用得比較普遍。

SpringBoot通過yml進(jìn)行配置

在SpringBoot項(xiàng)目中,我們得配置項(xiàng)一般都是配置在yml文件中,這樣就能和代碼分開,并且也能進(jìn)行動(dòng)態(tài)配置。

從上面我們看出可以通過好幾種方式進(jìn)行配置,但是他們最終其實(shí)都是將環(huán)境變量設(shè)置進(jìn)Environment中,這樣,spring在后續(xù)得流程里面,就能從Environment中獲取環(huán)境變量,然后進(jìn)行相應(yīng)的邏輯處理。

源碼解析

BeanDefinition注冊

首先,需要注冊bean的元信息BeanDefinition,不過對于@Profile標(biāo)注的方法,如果環(huán)境變量中有對應(yīng)的變量值,那么就能注冊,沒有的話則不會(huì)進(jìn)行注冊,我們來看關(guān)鍵的代碼,在ConfigurationClassBeanDefinitionReader中,有一個(gè)shouldSkip判斷,它會(huì)篩選出符合的bean,不符合條件的bean則被加入skippedBeanMethods集合中,不會(huì)被注冊。

private void loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) {
	ConfigurationClass configClass = beanMethod.getConfigurationClass();
	MethodMetadata metadata = beanMethod.getMetadata();
	String methodName = metadata.getMethodName();
		// Do we need to mark the bean as skipped by its condition?
	if (this.conditionEvaluator.shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN)) {
            configClass.skippedBeanMethods.add(methodName);
            return;
	}
            if (configClass.skippedBeanMethods.contains(methodName)) {
            return;
	}
}

shouldSkip源碼

在shouldSkip中,會(huì)使用Condition接口,@Profile使用的是ProfileCondition,然后調(diào)用matches方法。

    public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationCondition.ConfigurationPhase phase) {
        for (Condition condition : conditions) {
            ConfigurationCondition.ConfigurationPhase requiredPhase = null;
            if (condition instanceof ConfigurationCondition configurationCondition) {
                requiredPhase = configurationCondition.getConfigurationPhase();
            }
            if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
                return true;
            }
        }
        return false;
    }

ProfileCondition匹配

在ProfileCondition的matches方法中,主要就是去Environment中尋找環(huán)境變量,然后解析@Profile注解設(shè)置的value值,如果Environment中激活的配置中包含當(dāng)前的配置,包含則能為true,不包含則為false,如上通過setActiveProfiles設(shè)置Environment中激活的配置為dev,當(dāng)前傳過來的配置為dev,那么就能匹配上,就能裝配進(jìn)IOC容器。

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
        if (attrs != null) {
            for (Object value : attrs.get("value")) {
                if (context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value))) {
                    return true;
                }
            }
            return false;
        }
        return true;
    }

從源碼可以看出,其最核心的思想就是是否注冊bean的元信息BeanDefinition,因?yàn)橹挥凶粤薆eanDefinition,后續(xù)才能為創(chuàng)建bean提供元數(shù)據(jù)支持,判斷是否注冊bean元信息,主要就是從Environment中取出profiles的值,然后和@Profile注解設(shè)置的值進(jìn)行匹配,匹配得上就注冊,bean不上就不注冊。

總結(jié)

上面我們對@Profile的使用做了詳細(xì)的介紹,并對它的核心源碼進(jìn)行解剖,無非就是判斷是否要注冊BeanDefinition,如果我們需要做一些環(huán)境隔離的工作,使用@Profile還是比較不錯(cuò)的。

到此這篇關(guān)于詳解Spring @Profile注解的使用和源碼解析的文章就介紹到這了,更多相關(guān)Spring @Profile注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Nacos多環(huán)境的實(shí)現(xiàn)過程

    Nacos多環(huán)境的實(shí)現(xiàn)過程

    本文介紹Nacos實(shí)現(xiàn)多環(huán)境的方案,包括單租戶和多租戶兩種類型,詳細(xì)介紹了如何在Nacos中創(chuàng)建命名空間、配置文件和項(xiàng)目,并通過配置文件的DataId和Group區(qū)分不同環(huán)境和項(xiàng)目,作者通過實(shí)戰(zhàn)場景展示了如何配置和啟動(dòng)項(xiàng)目,驗(yàn)證了配置文件的讀取和隔離效果
    2024-12-12
  • Java字符串?dāng)?shù)組的創(chuàng)建代碼示例

    Java字符串?dāng)?shù)組的創(chuàng)建代碼示例

    這篇文章主要介紹了Java中字符串?dāng)?shù)組的聲明、初始化、默認(rèn)值、遍歷和常見操作,文中通過代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2025-03-03
  • 詳解springboot接口如何優(yōu)雅的接收時(shí)間類型參數(shù)

    詳解springboot接口如何優(yōu)雅的接收時(shí)間類型參數(shù)

    這篇文章主要為大家詳細(xì)介紹了springboot的接口如何優(yōu)雅的接收時(shí)間類型參數(shù),文中為大家整理了三種常見的方法,希望對大家有一定的幫助
    2023-09-09
  • SpringCloud集成sleuth和zipkin實(shí)現(xiàn)微服務(wù)鏈路追蹤的實(shí)戰(zhàn)分享

    SpringCloud集成sleuth和zipkin實(shí)現(xiàn)微服務(wù)鏈路追蹤的實(shí)戰(zhàn)分享

    最近項(xiàng)目上準(zhǔn)備引入接口調(diào)用鏈路追蹤,說到這個(gè)我們就不得不想到springcloud全家桶中的sleuth了,他可以將跨多個(gè)服務(wù)請求鏈路記錄下來,供我們查詢分析,所以今天就分享一期微服務(wù)架構(gòu)接入sleuth+zipkin實(shí)戰(zhàn)演示,需要的朋友可以參考下
    2024-12-12
  • springboot應(yīng)用服務(wù)啟動(dòng)事件的監(jiān)聽實(shí)現(xiàn)

    springboot應(yīng)用服務(wù)啟動(dòng)事件的監(jiān)聽實(shí)現(xiàn)

    本文主要介紹了springboot應(yīng)用服務(wù)啟動(dòng)事件的監(jiān)聽實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • JVM內(nèi)存結(jié)構(gòu):程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧

    JVM內(nèi)存結(jié)構(gòu):程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧

    JVM 基本上是每家招聘公司都會(huì)問到的問題,它們會(huì)這么無聊問這些不切實(shí)際的問題嗎?很顯然不是。由 JVM 引發(fā)的故障問題,無論在我們開發(fā)過程中還是生產(chǎn)環(huán)境下都是非常常見的
    2021-06-06
  • Spring 中使用Quartz實(shí)現(xiàn)任務(wù)調(diào)度

    Spring 中使用Quartz實(shí)現(xiàn)任務(wù)調(diào)度

    這篇文章主要介紹了Spring 中使用Quartz實(shí)現(xiàn)任務(wù)調(diào)度,Spring中使用Quartz 有兩種方式,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • IDEA報(bào)錯(cuò):java?找不到符號圖文解決過程

    IDEA報(bào)錯(cuò):java?找不到符號圖文解決過程

    這篇文章主要給大家介紹了關(guān)于IDEA報(bào)錯(cuò):java?找不到符號解決的相關(guān)資料,運(yùn)行項(xiàng)目時(shí)Idea報(bào)錯(cuò),提示找不到符號,但是這個(gè)類在項(xiàng)目里是存在的,網(wǎng)上找了很多文章都沒解決,浪費(fèi)了一個(gè)下午終于弄好了,記錄一下,需要的朋友可以參考下
    2023-08-08
  • java獲取當(dāng)前時(shí)間戳的方法

    java獲取當(dāng)前時(shí)間戳的方法

    本文主要介紹了java獲取當(dāng)前時(shí)間戳的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • RabbitMQ消息隊(duì)列中多路復(fù)用Channel信道詳解

    RabbitMQ消息隊(duì)列中多路復(fù)用Channel信道詳解

    這篇文章主要介紹了RabbitMQ消息隊(duì)列中多路復(fù)用Channel信道詳解,消息Message是指在應(yīng)用間傳送的數(shù)據(jù),消息可以非常簡單,比如只包含文本字符串,也可以更復(fù)雜,可能包含嵌入對象,需要的朋友可以參考下
    2023-08-08

最新評論

城口县| 东莞市| 宁阳县| 海阳市| 满洲里市| 龙川县| 潮州市| 广州市| 全州县| 长葛市| 西平县| 天等县| 原阳县| 蓝山县| 临湘市| 政和县| 南皮县| 原平市| 滦平县| 安西县| 都匀市| 新郑市| 玉环县| 玛多县| 邓州市| 霍州市| 香格里拉县| 冷水江市| 砀山县| 锡林浩特市| 甘谷县| 全椒县| 敦煌市| 射阳县| 九寨沟县| 阳泉市| 灵川县| 正宁县| 晋州市| 大田县| 车险|