1概要

Spring Bootでは、個別のコンテキストを作成して階層構造にまとめることができます。

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

Spring Bootアプリケーションの設定方法については詳しく説明しませんが、/spring-boot-start[article]のリンクを確認してください。


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

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

  • コンテキスト階層は、複数の子コンテキストが親コンテキストに存在するBeanを共有することを可能にします** 各子コンテキストは、親コンテキストから継承された設定をオーバーライドできます。

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

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


3

SpringApplicationBuilder

API

を使用する


SpringApplicationBuilder

クラスは、

parent()



__child()


および

sibling()__メソッドを使用してコンテキスト間の親子関係を作成するための流暢なAPIを提供します。

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

これを実証するために、2つの埋め込みTomcatインスタンスをそれぞれ独自のWebアプリケーションコンテキストで起動し、両方とも単一のJVMで実行します。


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=8081
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コンテキスト用のコントローラーを追加します。

@Controller
public class Ctx1Controller {

    @Autowired
    HomeService homeService;

    @GetMapping("/home")
    @ResponseBody
    public String greeting() {

        return homeService.getGreeting();
    }
}

3.3. 兄弟コンテキスト

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

今回は、

homeService

Beanを作成しません。親コンテキストからアクセスするためです。

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

server.port=8082
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
    IHomeService homeService;

    @GetMapping(value = "/greeting", produces = "application/json")
    public String getGreeting() {
        return homeService.getGreeting();
    }
}

この場合、コントローラは親コンテキストから

homeService

beanを取得する必要があります。

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:8081/ctx1/home


and

localhost:8082/ctx2/greeting.__を使用して、それぞれのポートで両方のアプリケーションにアクセスできます。

4.まとめ


SpringApplicationBuilder

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

例のソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-ctx-fluent[over on GitHub]から入手できます。