1. 序章

この短いチュートリアルでは、SpringでBeanを動的に自動配線する方法を示します。

まず、動的自動配線が役立つ可能性のある実際のユースケースを紹介します。 これに加えて、2つの異なる方法でSpringでそれを解決する方法を示します。

2. 動的自動配線の使用例

動的自動配線は、SpringのBean実行ロジックを動的に変更する必要がある場所で役立ちます。 これは、実行するコードがいくつかのランタイム変数に基づいて選択される場所で特に実用的です。

実際のユースケースを示すために、世界のさまざまな地域のサーバーを制御するアプリケーションを作成しましょう。 このため、2つの簡単な方法でインターフェースを作成しました。

public interface RegionService {
    boolean isServerActive(int serverId);

    String getISOCountryCode();
}

および2つの実装:

@Service("GBregionService")
public class GBRegionService implements RegionService {
    @Override
    public boolean isServerActive(int serverId) {
        return false;
    }

    @Override
    public String getISOCountryCode() {
        return "GB";
    }
}
@Service("USregionService")
public class USRegionService implements RegionService {
    @Override
    public boolean isServerActive(int serverId) {
        return true;
    }

    @Override
    public String getISOCountryCode() {
        return "US";
    }
}

サーバーが選択した地域でアクティブであるかどうかをユーザーが確認できるWebサイトがあるとします。 したがって、ユーザーの入力を指定して、RegionServiceインターフェイスの実装を動的に変更するサービスクラスが必要です。 間違いなく、これは動的Bean自動配線が機能するユースケースです。

3. BeanFactoryを使用する

BeanFactory は、SpringBeanコンテナーにアクセスするためのルートインターフェースです。 特に、特定のBeanを取得するための便利なメソッドが含まれています。 BeanFactoryもSpringBeanであるため、自動配線してクラスで直接使用できます。

@Service
public class BeanFactoryDynamicAutowireService {
    private static final String SERVICE_NAME_SUFFIX = "regionService";
    private final BeanFactory beanFactory;

    @Autowired
    public BeanFactoryDynamicAutowireService(BeanFactory beanFactory) {
        this.beanFactory = beanFactory;
    }

    public boolean isServerActive(String isoCountryCode, int serverId) {
        RegionService service = beanFactory.getBean(getRegionServiceBeanName(isoCountryCode), 
          RegionService.class);

        return service.isServerActive(serverId);
    }

    private String getRegionServiceBeanName(String isoCountryCode) {
        return isoCountryCode + SERVICE_NAME_SUFFIX;
    }
}

getBean()メソッドのオーバーロードされたバージョンを使用して、指定された名前と目的のタイプのBeanを取得しました。

これは機能しますが、実際にはもっと慣用的なものに依存したいと思います。 つまり、依存性注入を使用するものです。

4. インターフェイスの使用

依存性注入でこれを解決するために、Springのあまり知られていない機能の1つに依存します。

標準の単一フィールド自動配線に加えて、 Springは、特定のインターフェースの実装であるすべてのBeanをMapに収集する機能を提供します。

@Service
public class CustomMapFromListDynamicAutowireService {
    private final Map<String, RegionService> servicesByCountryCode;

    @Autowired
    public CustomMapFromListDynamicAutowireService(List<RegionService> regionServices) {
        servicesByCountryCode = regionServices.stream()
                .collect(Collectors.toMap(RegionService::getISOCountryCode, Function.identity()));
    }

    public boolean isServerActive(String isoCountryCode, int serverId) {
        RegionService service = servicesByCountryCode.get(isoCountryCode);

        return service.isServerActive(serverId);
    }
}

国コードによる実装を保持するコンストラクターでマップを作成しました。 さらに、後でメソッドで使用して、特定の実装を取得し、特定のサーバーが特定のリージョンでアクティブであるかどうかを確認できます。

5. 結論

このクイックチュートリアルでは、2つの異なるアプローチを使用してSpringでBeanを動的に自動配線する方法を説明しました。

いつものように、この記事に示されているコードは、GitHubから入手できます。