AnnotationConfigApplicationContext に profile をセットして使用する

今回の検証内容のリポジトリ

ComponentScan の設定を記載したクラスを用意。

@ComponentScan("com.diExperiment")
public class AppConfig {
}

他のクラスと依存している ProductPriceListReportService のコンストラクタ。 インターフェースである PriceListReport を引数にとるようにすることで結合度を下げる。

// コンストラクターインジェクション
public ProductPriceListReportService(ProductDao productDao, ProductPriceCalculator productPriceCalculator,PriceListReport priceListReport) {
    this.productDao = productDao;
    this.productPriceCalculator = productPriceCalculator;
    this.priceListReport = priceListReport;
}

とはいっても、DIコンテナを使わない場合は、 ProductPriceListReportService 作成時に、実装クラスを渡してあげることになる。

var productPriceListReportService = new ProductPriceListReportService(
        new ProductDao(),
        new ProductPriceCalculator(),
        // new PdfPriceListReport()
        new XlsPriceListReport()
);
productPriceListReportService.generateReport();

AnnotationConfigApplicationContext(DIコンテナ)を使う場合。

まずは、実装クラスに Profile を指定する。

@Component
@Profile("pdf-reports")
public class PdfPriceListReport implements PriceListReport {

    @Override
    public void writeReport(List<PriceList> priceLists) {
        System.out.println("Making Pdf Reports");
    }
}
@Component
@Profile("xls-reports")
public class XlsPriceListReport implements PriceListReport {

    @Override
    public void writeReport(List<PriceList> priceLists) {
        System.out.println("Making Xls Reports");
    }
}

Active Profiles をセットしてから、 AppConfig を登録することで、コンポーネントスキャンする際に、 Profile にて指定した実装クラスが Bean 登録される。

public static void main(String[] args) {

    AnnotationConfigApplicationContext context = getSpringContext("pdf-reports");
    // AnnotationConfigApplicationContext context = getSpringContext("xls-reports");
    var productPriceListReportService = context.getBean(ProductPriceListReportService.class);
    productPriceListReportService.generateReport();

    // 自分で登録した Bean を表示する
    System.out.println("\n--------- all custom defined beans in our applicationContext container ---------");
    String[] beanDefinitionNames = context.getBeanDefinitionNames();
    Arrays.stream(beanDefinitionNames)
            .filter(name -> !name.contains("org.springframework.context"))
            .forEach(System.out::println);

    context.close();
}

private static AnnotationConfigApplicationContext getSpringContext(String profile) {
    var context = new AnnotationConfigApplicationContext();
    context.getEnvironment().setActiveProfiles(profile);
    context.register(AppConfig.class);
    // context.scan("com.diExperiment"); // if you don't use AppConfig class
    context.refresh();
    return context;
}

実行結果。

Finding all product
Calculating product prices
Making Pdf Reports

--------- all custom defined beans in our applicationContext container ---------
appConfig
productPriceCalculator
productDao
pdfPriceListReport
productPriceListReportService