@プロファイルの使用シナリオ

序文

実際の企業の開発環境では、開発環境、テスト環境、本番環境に分けられることが多く、各環境は基本的に互いに分離されており、開発環境、テスト環境、本番環境は相互に排他的です。 . 関係ありません。以前の開発プロセスでは、開発者が対応する機能モジュールを完成させて単体テストに合格した場合、構成ファイルを手動で変更してプロジェクトの構成をテスト環境に変更し、テストのためにテスト環境にリリースしていました。テストに合格したら、構成を実稼働環境に変更し、実稼働環境にリリースします。このように構成を手動で変更する方法では、開発や運用保守の負荷が増大する一方、さまざまな構成ファイルを常に手動で変更すると問題が発生しやすくなります。では、これらの問題を解決する方法はあるのでしょうか? 答えは「はい」です。@Profile アノテーションを使用して完全に実行できます。

1. @Profile アノテーションの概要

コンテナ内に同じタイプのコンポーネントが複数ある場合、 @Profile アノテーションを使用して取得する Bean を識別することもできます。これは、異なる環境で異なる変数を使用する場合に特に便利です。例えば、開発環境、テスト環境、本番環境で異なるデータソースを使用する場合、このアノテーションを利用することで、コードを変更することなく接続するデータベースを切り替えることができます。

次のように進めます。

  1. @Profile アノテーションを Bean に追加します。その value 属性値はカスタマイズ可能な環境識別子です。
  2. 引数なしのコンストラクターを使用してコンテナーを作成する
  3. コンテナ環境を設定します。値は手順 1 で設定した環境 ID です。
  4. コンテナの構成クラスを設定する
  5. コンテナをリフレッシュする

注: ステップ 2、4、および 5 は、実際にはパラメータ付きの構築メソッドのステップであり、パラメータ付きの構築メソッドを逆アセンブルし、コンテナ環境を設定するステートメントを挿入することに相当します。これらは Spring のソース コードで確認できます。 、次のコードのように。

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    
    
   this();
   register(annotatedClasses);
   refresh();
}

次に、以下に示す @Profile アノテーションのソース コードを見てみましょう。

package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Profiles;
@Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
    
    
 String[] value();
}

注: @Profile はメソッドだけでなく構成クラスにもマークできます。
構成クラスにマークを付けた場合、構成クラス全体のすべての構成は、指定された環境でのみ有効になります。
Bean に @Profile アノテーションが付けられていない場合、Bean はどの環境でも IOC コンテナに登録されます。

2. @Profile アノテーションの使用

1. 環境構築

次に、 @Profile アノテーションを利用して、開発環境、テスト環境、本番環境の構成と切り替えを実現する環境を構築してみましょう。ここでは、さまざまなデータソースを例として取り上げます。まず、以下に示すように、c3p0 と MySQL ドライバーの依存関係を pom.xml ファイルに追加します。

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.44</version>
</dependency>

プロジェクトの依存関係を追加した後、以下に示すように、プロジェクト内に新しい ProfileConfig 構成クラスを作成し、ProfileConfig 構成クラスで開発、テスト、および運用環境のデータ ソースをシミュレートします。

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author 
 * @version 1.0.0
 * @description 测试多数据源
 */
@Configuration
public class ProfileConfig {
    
    
    @Bean("devDataSource")
    public DataSource dataSourceDev() throws Exception{
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_dev");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        return dataSource;
    }
    @Bean("testDataSource")
    public DataSource dataSourceTest() throws Exception{
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_test");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        return dataSource;
    }
    @Bean("prodDataDource")
    public DataSource dataSourceProd() throws Exception{
    
    
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_prod");
        dataSource.setUser("root");
        dataSource.setPassword("root");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        return dataSource;
    }
}

このクラスは比較的単純で、開発環境で使用されるデータ ソースに注釈を付けるために @Bean("devDataSource") アノテーションが使用され、テスト環境で使用されるデータ ソースに注釈を付けるために @Bean("testDataSource") アノテーションが使用されます。 ; use @Bean ("prodDataDource") アノテーションは、運用環境で使用されるデータ ソースをマークします。

次に、以下に示すように、ProfileTest クラスを作成し、テスト用に ProfileTest クラスに新しい testProfile01() メソッドを作成します。

import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.sql.DataSource;
import java.util.stream.Stream;

/**
 * @author 
 * @version 1.0.0
 * @description 测试类
 */
public class ProfileTest {
    
    
    @Test
    public void testProfile01(){
    
    
        // 创建IOC容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProfileConfig.class);
        String[] names = context.getBeanNamesForType(DataSource.class);
        Stream.of(names).forEach(System.out::println);
    }
}

ProfileTest クラスの testProfile01() メソッドを実行すると、出力情報は次のようになります。

devDataSource
testDataSource
prodDataDource

3 つの異なるデータ ソースが IOC コンテナに正常に登録されていることがわかり、環境が正常に構築されたことがわかります。

2. 環境に合わせてBeanを登録する

環境の構築が成功したら、次のステップは、さまざまな環境に応じて、対応する Bean を IOC コンテナに登録することです。つまり、開発環境で使用したデータソースを開発環境に登録し、テスト環境で使用したデータソースをテスト環境に登録し、本番環境で使用したデータソースを本番環境に登録する必要があります。この時点で、@Profile アノテーションの強力な機能がわかります。

以下に示すように、ProfileConfig クラスの各データ ソースに @Profile アノテーションを追加します。

@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_dev");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_test");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}
@Profile("prod")
@Bean("prodDataDource")
public DataSource dataSourceProd() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_prod");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}

@Profile("dev") アノテーションを使用して、開発環境に登録されている devDataSource を識別します。@Profile("test") アノテーションを使用して、テスト環境に登録されている testDataSource を識別します。@Profile("prod") アノテーションを使用します。本番環境を識別するためのアノテーション。 prodDataDource を環境に登録します。

この時点で、ProfileTest クラスの testProfile01() メソッドを実行すると、コマンド ラインに結果情報が出力されないことがわかります。異なるデータソースに @Profile アノテーションを追加すると、デフォルトでは Bean が IOC コンテナに登録されないため、環境の表示に従って、対応する Bean を IOC コンテナに登録する必要があることを説明します。

言い換えると、@Profile アノテーションによって環境でマークされた Bean は、環境がアクティブ化された場合にのみ IOC コンテナに登録されます。

デフォルトの環境が必要な場合はどうすればよいでしょうか?
この時点で、@Profile("default") アノテーションを使用してデフォルト環境を識別できます。たとえば、以下に示すように、devDataSource 環境をデフォルト環境として識別します。

@Profile("default")
@Bean("devDataSource")
public DataSource dataSourceDev() throws Exception{
    
    
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_dev");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    return dataSource;
}

この時点で、ProfileTest クラスの testProfile01() メソッドを実行すると、出力情報は次のようになります。

devDataSource

ご覧のとおり、devDataSource データ ソースに @Profile("default") アノテーションを使用してデフォルト データ ソースとして設定し、テスト メソッドの実行時にコマンド ラインで devDataSource が出力されます。

次に、devDataSource データ ソースの @Profile("default") アノテーションを @Profile("dev") アノテーションに復元し、開発環境に登録されたデータ ソースとして識別します。

では、異なる環境に応じて対応する Bean を登録するにはどうすればよいでしょうか?

1 つ目の方法は、コマンド ライン パラメーターに基づいて環境を決定することです。プログラムの実行時に、対応するコマンド ライン パラメーターを追加できます。たとえば、現在の環境はテスト環境なので、プログラムの実行時に次のコマンド ライン パラメーターを追加できます。 。

-Dspring.profiles.active=test

2 番目の方法は、AnnotationConfigApplicationContext クラスの引数なしの構築メソッドを使用する方法です。プログラム内で AnnotationConfigApplicationContext の引数なしの構築メソッドを呼び出して IOC コンテナを生成します。コンテナが初期化される前に、IOC コンテナに対応する環境を設定し、次に IOC コンテナのメイン構成クラスを設定します。たとえば、以下に示すように、本番環境として IOC コンテナをセットアップします。

@Test
public void testProfile02(){
    
    
    //创建IOC容器
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.getEnvironment().setActiveProfiles("prod");
    context.register(ProfileConfig.class);
    context.refresh();
    String[] names = context.getBeanNamesForType(DataSource.class);
    Stream.of(names).forEach(System.out::println);
}

この時点で、testProfile02() メソッドを実行すると、出力情報は次のようになります。

prodDataDource

コマンド ラインが prodDataDource を出力し、IOC 環境が実稼働環境に正常に設定されたことを示していることがわかります。

@Profile はメソッドだけでなく構成クラスにもマークできます。構成クラスにマークを付けた場合、構成クラス全体のすべての構成は、指定された環境でのみ有効になります。たとえば、以下に示すように、ProfileConfig クラスに @Profile("dev") アノテーションを付けます。

@Profile("dev")
@Configuration
public class ProfileConfig {
    
    
    /*********代码省略*********/
}

次に、testProfile02() メソッドを実行すると、コマンド ラインに情報が出力されないことがわかります。

これは、testProfile02() メソッドで現在の環境を運用環境として指定しており、ProfileConfig クラスのアノテーションが @Profile("dev") であり、ProfileConfig クラスのすべての構成が開発環境でのみ有効であることを示しているためです。環境も したがって、現時点では IOC コンテナにデータ ソースが登録されておらず、コマンド ラインは情報を出力しません。

おすすめ

転載: blog.csdn.net/qq_36602071/article/details/129874062