1. 概述
可以在 Spring Boot 中創建單獨的上下文並將其組織成層次結構。
Spring Boot 應用程序可以以多種方式定義上下文層次結構。 在本文中,我們將探討如何使用流暢構建器 API 創建多個上下文。
由於我們將不深入討論如何設置 Spring Boot 應用程序,因此您可能想查看這篇文章。
2. 應用程序上下文層次結構
我們可以擁有多個應用程序上下文,它們之間存在父子關係。
上下文層次結構允許多個子上下文共享位於父上下文中的 Bean。 每個子上下文都可以覆蓋從父上下文繼承的配置。
此外,我們可以使用上下文來防止一個上下文中的 Bean 在另一個上下文中的可訪問性。這有助於創建鬆散耦合的模塊。
需要注意的是,一個上下文只能有一個父上下文,而一個父上下文可以有多個子上下文。 此外,子上下文可以訪問父上下文中的 Bean,但反之則不然。
3. 使用 <em >SpringApplicationBuilder</em > API
<em >SpringApplicationBuilder</em >> 類提供了一個流暢的 API,用於使用parent()>、<em >child()</em >> 和sibling()> 方法來創建父子上下文關係。
為了説明上下文層次結構,我們將設置一個非 Web 父級應用程序上下文,幷包含 2 個子級 Web 上下文。
為了演示這一點,我們將啓動兩個嵌入式 Tomcat 實例,每個實例都有自己的 Web 應用程序上下文,並且它們都運行在單個 JVM 中。
3.1. 父級上下文
首先,讓我們創建一個服務 Bean 及其 Bean 定義類,這些類位於父級包中。我們希望這個 Bean 返回一個問候語,該問候語將顯示給我們的 Web 應用程序的客户端:
@Service
public class HomeService implements IHomeService {
public String getGreeting() {
return "Welcome User";
}
}<p>以及 Bean 定義類:</p>
@Configuration
@ComponentScan("com.baeldung.parent")
public class ServiceConfig {}接下來,我們將創建兩個子上下文的配置。
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 豆的定義,它將覆蓋父類中的定義。
讓我們查看 GreetingService 類的定義:
@Service
public class GreetingService implements IHomeService {
public String getGreeting() {
return "Greetings for the day";
}
}最後,我們將為這個 Web 上下文添加一個控制器,它將使用 homeService Bean 來向用户顯示一條消息:
@RestController
public class Ctx1Controller {
@Autowired
private HomeService homeService;
@GetMapping("/home")
public String greeting() {
return homeService.getGreeting();
}
}3.3. 兄弟上下文
對於我們第二個上下文,我們將創建一個與上一節中非常相似的控制器和配置類。
這次我們不會創建一個 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();
}
}在這種情況下,我們的控制器應該從父上下文中獲取 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 應用時,我們可以通過 localhost:8074/ctx1/home 和 localhost:8075/ctx2/greeting 這兩個端口訪問這兩個應用程序。
4. 結論
使用 <em >SpringApplicationBuilder</em> API,我們首先創建了應用程序兩個上下文之間的父子關係。 接下來,我們介紹瞭如何在子上下文中覆蓋父上下文的配置。 最後,我們添加了一個兄弟上下文,以演示父上下文的配置可以與其他子上下文共享。