1. 程式人生 > >Spring入門(六):條件化的bean

Spring入門(六):條件化的bean

1. 概念

預設情況下,Spring中定義的bean在應用程式啟動時會全部裝配,不管當前執行的是哪個環境(Dev,QA或者Prod),也不管當前執行的是什麼系統(Windows或者Linux),但有些使用場景下,我們可能需要條件化的裝配某些bean,即當滿足某一條件時,裝配某些bean,當不滿足某一條件時,就忽略掉某些bean。

這個條件可以很簡單,比如當某個jar包存在時,當存在某個環境變數時,也可以很複雜。

針對這個使用場景,Spring中提供了@Conditional註解來實現條件化的bean。

2. 示例

為了更好的理解,我們通過具體的程式碼示例來理解下條件化的bean的實現方式。

由於Windows系統和Linux系統顯示列表的命令不同,Windows下是dir,Linux下是ls,因此我們的需求是,應用程式啟動時自動根據當前系統裝配需要的bean,比如我的電腦系統是Windows 7,那就只裝配Windows系統所需要的bean。

首先,定義一個介面ListService,該介面只包含一個方法showListCmd:

package chapter03.conditional;

public interface ListService {
    String showListCmd();
}

然後定義該介面的2個實現類WindowsListService和LinuxListService:

package chapter03.conditional;

public class WindowsListService implements ListService {
    public WindowsListService() {
        System.out.println("This is WindowsListService constructor");
    }
    
    @Override
    public String showListCmd() {
        return "dir";
    }
}
package chapter03.conditional;

public class LinuxListService implements ListService {
    public LinuxListService() {
        System.out.println("This is LinuxListService constructor");
    }
    
    @Override
    public String showListCmd() {
        return "ls";
    }
}

然後分別定義Windows系統和Linux系統的判斷條件:

package chapter03.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class WindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        return conditionContext.getEnvironment().getProperty("os.name").contains("Windows");
    }
}
package chapter03.conditional;

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class LinuxCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        return conditionContext.getEnvironment().getProperty("os.name").contains("Linux");
    }
}

值得注意的是,這2個類都需要實現Condition介面,並重寫方法matches(),如果該方法返回true時,使用該條件的1個或多個bean就會被裝配,如果該方法返回false,使用該條件的1個或多個bean就會被忽略。

然後,定義Java配置類ConditionalConfig:

package chapter03.conditional;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConditionalConfig {
    @Bean
    @Conditional(WindowsCondition.class)
    public ListService windowsListService() {
        return new WindowsListService();
    }

    @Bean
    @Conditional(LinuxCondition.class)
    public ListService linuxListService() {
        return new LinuxListService();
    }
}

這裡宣告bean時除了使用@Bean註解,還使用了@Conditional註解,這個註解是實現條件化的bean的關鍵,它的引數可以傳遞任何實現了Condition介面並重寫了matches()方法的類,這裡傳遞的是我們上面定義的WindowsCondition和LinuxCondition。

最後,我們定義一個Main類,在其main()方法中新增如下測試程式碼:

package chapter03.conditional;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConditionalConfig.class);

        ListService listService = context.getBean(ListService.class);

        System.out.println(context.getEnvironment().getProperty("os.name") + "系統下的列表命令為:" + listService.showListCmd());

        context.close();
    }
}

執行結果如下所示:

This is WindowsListService constructor

Windows 7系統下的列表命令為:dir

從執行日誌可以看出,由於當前系統是Windows 7,我們宣告的linuxListService bean並沒有被裝配。

3. 原始碼及參考

原始碼地址:https://github.com/zwwhnly/spring-action.git,歡迎下載。

汪雲飛《Java EE開發的顛覆者:Spring Boot實戰》

Craig Walls 《Spring實戰(第4版)》

4. 最後

打個小廣告,歡迎掃碼關注微信公眾號:「申城異鄉人」,定期分享Java技術乾貨,讓我們一起進步。

相關推薦

Spring入門()條件bean

1. 概念 預設情況下,Spring中定義的bean在應用程式啟動時會全部裝配,不管當前執行的是哪個環境(Dev,QA或者Prod),也不管當前執行的是什麼系統(Windows或者Linux),但有些使用場景下,我們可能需要條件化的裝配某些bean,即當滿足某一條件時,裝配某些bean,當不滿足某一條件時,就

Spring入門(二)自動化裝配bean

pep 自動化 tdi req ngs mcr 完成 injection 實現類 Spring從兩個角度來實現自動化裝配: 組件掃描(component scanning):Spring會自動發現應用上下文中需要創建的bean。 自動裝配(autowiring):Spri

Spring Boot條件註解。

條件化註解 配置生效條件 @ConditionalOnBean 配置了某個特定Bean @ConditionalOnMissingBean 沒有配置特定的Bean

Spring Boot入門()使用MyBatis訪問MySql資料庫(註解方式)

本系列部落格記錄自己學習Spring Boot的歷程,如幫助到你,不勝榮幸,如有錯誤,歡迎指正! 本篇部落格我們講解下在Spring Boot中使用MyBatis訪問MySql資料庫的簡單用法。 1.前期準備 假設你的機器已經安裝好了MySql,我們先執行如下語句建立資料庫和表: CREATE DATAB

Spring入門(五)Spring Bean Scope講解

1. 前情回顧 Spring入門(一):建立Spring專案 Spring入門(二):自動化裝配bean Spring入門(三):通過JavaConfig裝配bean Spring入門(四):使用Maven管理Spring專案 2. 什麼是Bean的Scope? Scope描述的是Spring容器是如何新

Jmeter Web 性能測試入門 ()Jmeter 解析 response 並傳遞 value

pre 數據 put -c beanshell shel val sed ima 解析response中的內容,並把獲取到的value傳遞到後續的request中,常用的方法就是在想要解析response的request上添加後置處理器本章介紹兩種常用的組件 BeanSh

spring cloud()Zuul的集成

zuul spring cloud java 1、概念 Zuul 是在雲平臺上提供動態路由,監控,彈性,安全等邊緣服務的框架。Zuul 相當於是設備和 Netflix 流應用的 Web 網站後端所有請求的前門。另外需要理解的概念就是反向代理和負載均衡,反向代理:就是外網向內網請求資源,並把

條件bean

term win trac activated sel 引入 named poll tom 天行健,君子以自強不息。——《周易》 應用場景   假設你希望一個或多個bean只有在應用的類路徑下包含特定的庫時才創建,希望某個bean只有當某個特定的bean也聲明了之後才會創建

Spring總結AOP(面向切面編程)

版本 int run 傳統 代碼 tid contex except unit 概述:   AOP(Aspect-Oriented Programming,面向切面的編程),它是可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。

使用Junit測試一個 spring靜態工廠實例bean 的例子,所有代碼都沒有問題,但是出現java.lang.IllegalArgumentException異常

沒有 異常 分享 article java exce 技術分享 實例 image 使用Junit測試一個spring靜態工廠實例化bean的例子,所有代碼都沒有問題,但是出現 java.lang.IllegalArgumentException 異常, 如下圖所示:  

spring入門() spring mvc+mybatis

odi 創建 mode utf from 針對 namespace tid oca 1.引入依賴 1 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> 2 <depe

spring入門框架整體簡介

mil object web開發 spa tor 對象 j2ee 就是 cor 1:spring的基本框架主要包含六大模塊:DAO、ORM、AOP、JEE、WEB、CORE   DAO:(Data Access Object) 數據訪問對象,是一個面向對象的數據庫接口。  

腦殘式網路程式設計入門()什麼是公網IP和內網IP?NAT轉換又是什麼鬼?

本文引用了“帥地”發表於公眾號苦逼的碼農的技術分享。 1、引言 搞網路通訊應用開發的程式設計師,可能會經常聽到外網IP(即網際網路IP地址)和內網IP(即區域網IP地址),但他們的區別是什麼?又有什麼關係呢?另外,內行都知道,提到外網IP和內網IP就不得不提NAT路由轉換這種東西,那這雙是什

Spring入門(一)Spring注入

概念 Spring注入是指在啟動Spring容器載入bean配置的時候,完成對變數的賦值行為 常用的兩種注入方式 設值注入 構造注入 設值注入 <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns

spring boot()如何優雅的使用mybatis

這兩天啟動了一個新專案因為專案組成員一直都使用的是mybatis,雖然個人比較喜歡jpa這種極簡的模式,但是為了專案保持統一性技術選型還是定了 mybatis。到網上找了一下關於spring boot和mybatis組合的相關資料,各種各樣的形式都有,看的人心累,結合了m

java io詳解序列與反序列(物件流)

1、什麼是序列化與反序列化?   序列化:指把堆記憶體中的 Java 物件資料,通過某種方式把物件儲存到磁碟檔案中或者傳遞給其他網路節點(在網路上傳輸)。這個過程稱為序列化。通俗來說就是將資料結構或物件轉換成二進位制串的過程   反序列化:把磁碟檔案中的物件資料或者把網路節點上的物件資料,恢

PyTorch基礎入門PyTorch搭建卷積神經網路實現MNIST手寫數字識別

1)卷積神經網路(CNN)簡介 關於什麼是卷積神經網路(CNN),請自行查閱資料進行學習。如果是初學者,這裡推薦一下臺灣的李巨集毅的深度學習課程。連結就不給了,這些資料網站上隨處可見。 值得一提的是,CNN雖然在影象處理的領域具有不可阻擋的勢頭,但是它絕對不僅僅只能用來影

Spring Boot()如何使用mybatis

Spring Boot(六):如何使用mybatis orm框架的本質是簡化程式設計中操作資料庫的編碼,發展到現在基本上就剩兩家了,一個是宣稱可以不用寫一句SQL的hibernate,一個是可以靈活除錯動態sql的mybatis,兩者各有特點,在企業級系統開發中可以根據需求靈活使用。 目前情況:傳統企業大

Spring的三種例項Bean的方式

Spring提供了三種例項化Bean的方式。 使用類構造器例項化。 <bean id="personService" class="cn.itcast.service.impl.Person

Spring Boot()如何配置靜態資源的地址與訪問路徑

靜態資源,例如HTML檔案、JS檔案,設計到的Spring Boot配置有兩項,一是“spring.mvc.static-path-pattern”,一是“spring.resources.static-locations”,很多人都難以分辨它們之間的差異,所以