1. 程式人生 > >Spring入門(七):Spring Profile使用講解

Spring入門(七):Spring Profile使用講解

1. 使用場景

在日常的開發工作中,我們經常需要將程式部署到不同的環境,比如Dev開發環境,QA測試環境,Prod生產環境,這些環境下的一些配置肯定是不一樣的,比如資料庫配置,Redis配置,RabbitMQ配置。

如果每次切換髮布環境,都需要修改配置重新構建的話,那對程式設計師來說將是噩夢,針對這種場景,Spring提供了@Profile註解來實現按照不同的環境裝配不同的bean,進而實現程式只需構建一次,但可以部署到多個環境。

2. 配置profile bean

為了更好的理解,我們通過具體的程式碼示例來理解下Spring profile的使用方法,這裡我們以資料庫配置為例。

說明:本篇部落格的重點是講解@Profile註解的使用,資料庫的操作只是輔助理解@Profile,因此不會講解的太詳細,不過後續會單獨寫部落格講解

假設我們有3套環境(Dev,QA,Prod),這3套環境的資料庫都使用的是mysql,但是其地址,使用者名稱,密碼都不一樣,那麼在Java配置中,該如何宣告這些bean呢?

2.1 Java配置中配置profile bean

首先需要了解的是,@Profile註解是從Spring 3.1版本中開始引入的,並且在這個版本中,@Profile註解只能在類級別上使用。

因此我們可以按照環境分別建立資料庫配置,如下所示:

Dev環境下的資料庫配置:

package chapter03.profile;

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import javax.sql.DataSource;

@Configuration
@Profile("dev")
public class DevDataSourceConfig {
    @Bean
    public DataSource devDataSource() {
        System.out.println("This is dev DataSource");

        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_action_db");
        basicDataSource.setUsername("dev");
        basicDataSource.setPassword("dev");

        return basicDataSource;
    }
}

使用上述程式碼需要在pom.xml中新增如下依賴:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.7.0</version>
</dependency>

注意事項:如果類級別上使用了@Profile("dev"),那麼該類中的所有bean都會在profile為dev時建立。

QA環境下的資料庫配置:

package chapter03.profile;

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import javax.sql.DataSource;

@Configuration
@Profile("qa")
public class QADataSourceConfig {
    @Bean
    public DataSource qaDataSource() {
        System.out.println("This is qa DataSource");

        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3307/mybatis_action_db");
        basicDataSource.setUsername("qa");
        basicDataSource.setPassword("qa");

        return basicDataSource;
    }
}

Prod環境下的資料庫配置:

package chapter03.profile;

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import javax.sql.DataSource;

@Configuration
@Profile("prod")
public class ProdDataSourceConfig {
    @Bean
    public DataSource prodDataSource() {
        System.out.println("This is prod DataSource");

        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3308/mybatis_action_db");
        basicDataSource.setUsername("prod");
        basicDataSource.setPassword("prod");

        return basicDataSource;
    }
}

不過從Spring 3.2開始,@Profile註解可以與@Bean註解一起在方法級別上使用。

這也就使得我們可以將剛剛的3個配置類合併成1個配置類(推薦該方式),如下所示:

package chapter03.profile;

import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import javax.sql.DataSource;

@Configuration
public class DataSourceConfig {
    @Bean
    @Profile("dev")
    public DataSource devDataSource() {
        System.out.println("This is dev DataSource");

        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_action_db");
        basicDataSource.setUsername("dev");
        basicDataSource.setPassword("dev");

        return basicDataSource;
    }

    @Bean
    @Profile("qa")
    public DataSource qaDataSource() {
        System.out.println("This is qa DataSource");

        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3307/mybatis_action_db");
        basicDataSource.setUsername("qa");
        basicDataSource.setPassword("qa");

        return basicDataSource;
    }

    @Bean
    @Profile("prod")
    public DataSource prodDataSource() {
        System.out.println("This is prod DataSource");

        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        basicDataSource.setUrl("jdbc:mysql://localhost:3308/mybatis_action_db");
        basicDataSource.setUsername("prod");
        basicDataSource.setPassword("prod");

        return basicDataSource;
    }
}

注意事項:沒有指定profile的bean始終都會建立,與啟用哪個profile無關。

2.2 xml中配置profile bean

我們也可以通過<beans>元素的profile屬性,在xml中配置profile bean,如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
       profile="dev">
    <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
          p:driverClassName="com.mysql.jdbc.Driver"
          p:url="jdbc:mysql://localhost:3306/mybatis_action_db"
          p:username="dev"
          p:password="dev"/>
</beans>

可以參考該配置,分別建立qa和prod環境的profile xml檔案。

不過還是推薦使用巢狀的<beans>元素,在一個xml檔案中配置好3個環境的資料來源,程式碼如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <beans profile="dev">
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
              p:driverClassName="com.mysql.jdbc.Driver"
              p:url="jdbc:mysql://localhost:3306/mybatis_action_db"
              p:username="dev"
              p:password="dev"/>
    </beans>
    <beans profile="qa">
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
              p:driverClassName="com.mysql.jdbc.Driver"
              p:url="jdbc:mysql://localhost:3307/mybatis_action_db"
              p:username="qa"
              p:password="qa"/>
    </beans>
    <beans profile="prod">
        <bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
              p:driverClassName="com.mysql.jdbc.Driver"
              p:url="jdbc:mysql://localhost:3308/mybatis_action_db"
              p:username="prod"
              p:password="prod"/>
    </beans>
</beans>

3. 啟用profile

截止目前,我們按照環境的維度建立了3個bean,但實際執行時,只會建立1個bean,具體建立哪個bean取決於處於啟用狀態的是哪個profile。

那麼,我們該如何啟用某個profile呢?

Spring在確定啟用哪個profile時,需要依賴2個屬性:

  1. spring.profiles.active
  2. spring.profiles.default

spring.profiles.active的優先順序比spring.profiles.default高,即如果沒有配置spring.profiles.active,就使用spring.profiles.default配置的值,如果配置了spring.profiles.active,就不會再使用spring.profiles.default配置的值。

如果兩者都沒有配置,就只會建立那些沒有定義profile的bean。

Web應用中,在web.xml中設定spring.profiles.active的程式碼如下所示:

<context-param>
    <param-name>spring.profiles.active</param-name>
    <param-value>dev</param-value>
</context-param>

也可以使用程式碼方式啟用:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();

context.getEnvironment().setActiveProfiles("dev");

4. 單元測試

新建Main類,在其main()方法中新增如下測試程式碼:

package chapter03.profile;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

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

        context.getEnvironment().setActiveProfiles("dev");
        context.register(DataSourceConfig.class);
        context.refresh();

        context.close();
    }
}

輸出結果如下所示:

This is dev DataSource

如果將程式碼修改為context.getEnvironment().setActiveProfiles("qa");,輸出結果為:

This is qa DataSource

如果將程式碼修改為context.getEnvironment().setActiveProfiles("prod");,輸出結果為:

This is prod DataSource

5. 原始碼及參考

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

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

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

6. 最後

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

相關推薦

Spring入門()Spring Profile使用講解

1. 使用場景 在日常的開發工作中,我們經常需要將程式部署到不同的環境,比如Dev開發環境,QA測試環境,Prod生產環境,這些環境下的一些配置肯定是不一樣的,比如資料庫配置,Redis配置,RabbitMQ配置。 如果每次切換髮布環境,都需要修改配置重新構建的話,那對程式設計師來說將是噩夢,針對這種場景,S

Spring入門(五)Spring Bean Scope講解

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

Spring入門(十)Spring AOP使用講解

1. 什麼是AOP? AOP是Aspect Oriented Programming的縮寫,意思是:面向切面程式設計,它是通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。 可以認為AOP是對OOP(Object Oriented Programming 面向物件程式設計)的補充,主要使用在日誌

Spring入門(十三)Spring MVC常用註解講解

在使用Spring MVC開發Web應用程式時,控制器Controller的開發非常重要,雖然說檢視(JSP或者是Thymeleaf)也很重要,因為它才是直接呈現給使用者的,不過由於現在前端越來越重要,很多公司都開始採用前後端分離的開發模式,所以我們暫時可以將精力放在開發控制器上。 使用Spring MVC開

Spring入門(一)Spring注入

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

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

本系列部落格帶你一步一步的學習Spring Boot,如幫助到你,不勝榮幸,如有錯誤,歡迎指正! 本篇部落格我們講解下在Spring Boot中使用MyBatis訪問MySql資料庫(xml方式)的簡單用法。 本系列其它文章如下所示: Spring Boot入門(一):使用IDEA建立Spring Boo

《Java從入門到放棄》入門spring中IOC的註入姿勢

java ioc spring IOC到底是個什麽東東呢?控制反轉(Inversion of Control,英文縮寫為IoC),其實就是這個東東。你隨便百度一下就會得到比較書面的解釋:通過引入實現了IoC模式的IoC容器,即可由IoC容器來管理對象的生命周期、依賴關系等,從而使得應用程序的配置和

Spring Boot系列教程Spring boot集成MyBatis

override fill sql water sso avi size logs index 一.創建項目 項目名稱為 “springboot_mybatis_demo”,創建過程中勾選 “Web”,“MyBatis”,“MySQL”,第一次創建Maven

《01.Spring Boot連載Spring Boot入門介紹》

spring boot maven 1 Spring Boot的概述Spring Boot是開發者和Spring 本身框架的中間層,幫助開發者統籌管理應用的配置,提供基於實際開發中常見配置的默認處理(即習慣優於配置),簡化應用的開發,簡化應用的運維;總的來說,其目的Spring Boot就是為了對Ja

spring cloud()Hystrix的應用

hystrix java 微服務 1、概念 熔斷器,容錯管理工具,旨在通過熔斷機制控制服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。除了熔斷的功能還有服務降級、線程和信號隔離、請求緩存、請求合並以及服務監控等強大功能。2、集成 a、工程的 pom.xml 的

Spring Boot 2.0()Spring Boot 如何解決項目啟動時初始化資源

springboot在我們實際工作中,總會遇到這樣需求,在項目啟動的時候需要做一些初始化的操作,比如初始化線程池,提前加載好加密證書等。今天就給大家介紹一個 Spring Boot 神器,專門幫助大家解決項目啟動初始化資源操作。 這個神器就是 CommandLineRunner,CommandLineRunn

Spring總結AOP動態代理的實現

product div image style 攔截 throwable eth oid void Spring中的AOP代理可以使JDK動態代理,也可以是CGLIB代理,前者基於接口,後者基於子類。 首先我們來用代碼簡單演示jdk動態代理: 現在有一個商品的增刪改查的

spring入門框架整體簡介

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

Spring第一天Spring的概述、SpringIOC入門(XML)、Spring的Bean管理、Spring屬性注入

以前也學習過Spring框架,不過好久沒用,當時學完也沒做什麼總結,都忘的差不多了,今天再從頭開始學習一遍。無論是SSH還是SSM都離不開Spring,所以Spring還是很重要的,對於一個想要從事JavaEE開發的人,一定要好好學習Spring框架。Spring的學習計劃如下: 第一

SpringCloud實戰Spring Cloud Ribbon 實戰

前面的兩篇部落格已經講解了Feign作為服務間的呼叫,但是Feign是整合、封裝了Ribbonn這個元件而來的,讓服務間的呼叫更方便,因此大多使用Feign,本篇讓大家瞭解Ribbon的概念與呼叫 Ribbon是Netflix開發的一個負載均衡元件,它在服務體系中起著重要作用,Piv

Spring Boot 2.0()Spring Boot 如何解決專案啟動時初始化資源

在我們實際工作中,總會遇到這樣需求,在專案啟動的時候需要做一些初始化的操作,比如初始化執行緒池,提前載入好加密證書等。今天就給大家介紹一個 Spring Boot 神器,專門幫助大家解決專案啟動初始化資源操作。 這個神器就是 CommandLineRunner,CommandLineRunner 介面的 Co

深入Spring Boot ()靜態資源使用詳解

Web應用經常需要使用大量的靜態資源,如圖片、css、js等,Spring Boot對這些靜態資源的使用提供了預設配置。本篇將詳細介紹如何使用預設配置和如何修改這些預設配置,主要包含以下5部分內容: 1.靜態資源儲存路徑; 2.靜態資源訪問路徑; 3.最佳

Spring Cloud()鏈路追蹤Sleuth-Zipkin與Mysql資料的持久化

一:回顧 上節我們瞭解到Spring Cloud Sleuth可以實現對服務的追蹤,以及和Zipkin結合,可以視覺化服務追蹤介面和依賴等相關資訊。遺憾的是資料不能持久化。 二:專案的構建 構建三個專案sleuth-stream-server,sleu

Spring Cloud 3Spring Boot快速入門

簡介 在您第1次接觸和學習Spring框架的時候,是否因為其繁雜的配置而退卻了?在你第n次使用Spring框架的時候,是否覺得一堆反覆黏貼的配置有一些厭煩?那麼您就不妨來試試使用Spring Boot來讓你更易上手,更簡單快捷地構建Spring應用! Spring B

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

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