1. 概要

Spring Bootでは、個別のコンテキストを作成し、それらを階層に編成することができます。

コンテキスト階層は、SpringBootアプリケーションでさまざまな方法で定義できます。 この記事では、流暢なビルダーAPIを使用して複数のコンテキストを作成する方法を見ていきます。

Spring Bootアプリケーションの設定方法については詳しく説明しませんので、このの記事を確認することをお勧めします。

2. アプリケーションコンテキスト階層

親子関係を共有する複数のアプリケーションコンテキストを持つことができます。

コンテキスト階層により、複数の子コンテキストが親コンテキストに存在するBeanを共有できます。各子コンテキストは、親コンテキストから継承された構成をオーバーライドできます。

さらに、コンテキストを使用して、あるコンテキストに登録されたBeanが別のコンテキストでアクセスできないようにすることができます。 これにより、緩く結合されたモジュールの作成が容易になります。

ここで注目に値するいくつかのポイントは、親コンテキストが複数の子コンテキストを持つことができるのに対し、コンテキストは1つの親しか持つことができないということです。 また、子コンテキストは親コンテキストのBeanにアクセスできますが、その逆はできません。

3. SpringApplicationBuilderAPIの使用

SpringApplicationBuilder クラスは、 parent() child()、および sibling()[を使用してコンテキスト間の親子関係を作成するための流暢なAPIを提供します。 X180X]メソッド。

コンテキスト階層を例示するために、2つの子Webコンテキストを持つ非Web親アプリケーションコンテキストを設定します。

これを示すために、それぞれが独自のWebアプリケーションコンテキストを持ち、両方が単一のJVMで実行されている組み込みTomcatの2つのインスタンスを開始します。

3.1. 親コンテキスト

まず、親パッケージにあるBean定義クラスとともにサービスBeanを作成しましょう。 このBeanが、Webアプリケーションのクライアントに表示される挨拶を返すようにします。

@Service
public class HomeService implements IHomeService {

    public String getGreeting() {
        return "Welcome User";
    }
}

そして、Bean定義クラス:

@Configuration
@ComponentScan("com.baeldung.parent")
public class ServiceConfig {}

次に、2つの子コンテキストの構成を作成します。

3.2. 子コンテキスト

すべてのコンテキストはデフォルトの構成ファイルを使用して構成されているため、サーバーポートなどのコンテキスト間で共有できないプロパティに対して個別の構成を提供する必要があります。

競合する構成が自動構成によって取得されるのを防ぐために、クラスも別々のパッケージに保持します。

最初の子コンテキストのプロパティファイルを定義することから始めましょう。

server.port=8074
server.servlet.context-path=/ctx1

spring.application.admin.enabled=false
spring.application.admin.jmx-name=org.springframework.boot:type=Ctx1Rest,name=Ctx1Application

アプリケーション名が競合しないように、ポートとコンテキストパス、およびJMX名を構成したことに注意してください。

次に、このコンテキストのメイン構成クラスを追加しましょう。

@Configuration
@ComponentScan("com.baeldung.ctx1")
@EnableAutoConfiguration
public class Ctx1Config {
    
    @Bean
    public IHomeService homeService() {
        return new GreetingService();
    }
}

このクラスは、 homeService Beanの新しい定義を提供し、親からのものを上書きします。

GreetingServiceクラスの定義を見てみましょう。

@Service
public class GreetingService implements IHomeService {

    public String getGreeting() {
        return "Greetings for the day";
    }
}

最後に、 homeService Beanを使用してユーザーにメッセージを表示する、このWebコンテキスト用のコントローラーを追加します。

@RestController
public class Ctx1Controller {

    @Autowired
    private HomeService homeService;

    @GetMapping("/home")
    public String greeting() {
        return homeService.getGreeting();
    }
}

3.3. 兄弟コンテキスト

2番目のコンテキストでは、前のセクションのものと非常によく似たコントローラーと構成クラスを作成します。

今回は、 homeService Beanを作成しません。これは、親コンテキストからアクセスするためです。

まず、このコンテキストのプロパティファイルを追加しましょう。

server.port=8075
server.servlet.context-path=/ctx2

spring.application.admin.enabled=false
spring.application.admin.jmx-name=org.springframework.boot:type=WebAdmin,name=SpringWebApplication

そして、兄弟アプリケーションの構成クラス:

@Configuration
@ComponentScan("com.baeldung.ctx2")
@EnableAutoConfiguration
@PropertySource("classpath:ctx2.properties")
public class Ctx2Config {}

HomeServiceを依存関係として持つコントローラーも追加しましょう。

@RestController
public class Ctx2Controller {

    @Autowired
    private IHomeService homeService;

    @GetMapping("/greeting")
    public String getGreeting() {
        return homeService.getGreeting();
    }
}

この場合、コントローラーは親コンテキストからhomeServiceBeanを取得する必要があります。

3.4. コンテキスト階層

これで、すべてをまとめて、 SpringApplicationBuilder:を使用してコンテキスト階層を定義できます。

public class App {
    public static void main(String[] args) {
        new SpringApplicationBuilder()
          .parent(ParentConfig.class).web(WebApplicationType.NONE)
          .child(WebConfig.class).web(WebApplicationType.SERVLET)
          .sibling(RestConfig.class).web(WebApplicationType.SERVLET)
          .run(args);
    }
}

最後に、Spring Boot Appを実行すると、 localhost:8074 / ctx1 / homelocalhost:8075 / ctx2/greetingを使用してそれぞれのポートで両方のアプリケーションにアクセスできます。

4. 結論

SpringApplicationBuilder APIを使用して、最初にアプリケーションの2つのコンテキスト間に親子関係を作成しました。 次に、子コンテキストで親構成をオーバーライドする方法について説明しました。 最後に、兄弟コンテキストを追加して、親コンテキストの構成を他の子コンテキストと共有する方法を示しました。

この例のソースコードは、GitHubから入手できます。