知識庫 / Spring RSS 訂閱

Spring ApplicationContext 應用程序上下文

Spring
HongKong
5
12:50 PM · Dec 06 ,2025

1. 概述

在本教程中,我們將詳細探討 Spring ApplicationContext 接口。

2. <em>ApplicationContext</em> 接口

Spring 框架的主要功能之一是 IoC(控制反轉)容器。Spring IoC 容器負責管理應用程序的對象。它使用依賴注入來實現控制反轉。

Spring IoC 容器和 <em>BeanFactory</em> 接口代表 Spring IoC 容器。其中,<em>BeanFactory</em> 是訪問 Spring 容器的根接口,它提供基本的管理 Bean 的功能。

另一方面,<em>ApplicationContext</em><em>BeanFactory</em> 的子接口。因此,它提供了所有 <em>BeanFactory</em> 的功能。

此外,它還提供企業級特定功能<em>ApplicationContext</em> 的重要功能包括解析消息、支持國際化、發佈事件以及應用程序層特定上下文。因此,我們通常將其用作默認的 Spring 容器。

3. 什麼是 Spring Bean?

在深入瞭解 ApplicationContext 容器之前,瞭解 Spring Bean 非常重要。在 Spring 中,一個 Bean 是 Spring 容器實例化、組裝和管理的對象

所以,我們是否應該將應用程序的所有對象都配置為 Spring Bean? 實際上,作為最佳實踐,我們不應該這樣做。

根據 Spring 文檔,我們通常應該為服務層對象、數據訪問對象 (DAOs)、呈現對象以及 Hibernate SessionFactories、JMS 隊列等基礎設施對象定義 Bean。

此外,通常我們不應在容器中配置精細的領域對象。 創建和加載領域對象通常是 DAOs 和業務邏輯的責任。

現在,讓我們定義一個簡單的 Java 類,我們將用作本教程中的 Spring Bean:

public class AccountService {

  @Autowired
  private AccountRepository accountRepository;

  // getters and setters
}

4. 在容器中配置 Bean

正如我們所知,ApplicationContext 的主要職責是管理 Bean。

因此,應用程序必須向 ApplicationContext 容器提供 Bean 配置。 Spring Bean 配置包含一個或多個 Bean 定義。 此外,Spring 支持多種配置 Bean 的方式。

4.1. 基於Java的配置

首先,我們從基於Java的配置開始,因為它是在Spring 3.0版本及更高版本中最新且首選的方式。

基於Java的配置通常使用在<em @Bean</em>>-annotated 方法中,在<em @Configuration> 類中。<em @Bean</em>> 註解在一個方法中指示該方法創建Spring bean。 此外,使用<em @Configuration> 註解的類指示該類包含Spring bean配置。

現在,讓我們創建一個配置類來定義我們的`<em AccountService> 類作為Spring bean:

@Configuration
public class AccountConfig {

  @Bean
  public AccountService accountService() {
    return new AccountService(accountRepository());
  }

  @Bean
  public AccountRepository accountRepository() {
    return new AccountRepository();
  }
}

4.2. 基於註解的配置

Spring 2.5 引入了基於註解的配置作為啓用 Java 中 Bean 配置的第一步。

在這種方法中,我們首先通過 XML 配置啓用基於註解的配置。然後,我們使用一組註解來配置我們的 Java 類、方法、構造函數或字段。這些註解的例子包括 @Component@Controller@Service@Repository@Autowired@Qualifier

值得注意的是,我們使用這些註解與 Java 引導的配置一起使用。此外,Spring 會隨着每個發佈版本不斷增加這些註解的功能。

現在,讓我們來看一個簡單的配置示例。

首先,我們將創建 XML 配置,user-bean-config.xml,以啓用註解:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
  
  <context:annotation-config/>
  <context:component-scan base-package="com.baeldung.applicationcontext"/>

</beans>

在此,annotation-config 標籤啓用基於註解的映射。 component-scan 標籤也告訴 Spring 在哪裏查找帶有註解的類。

其次,我們將創建 UserService 類並使用 @Component 註解將其定義為 Spring Bean:

@Component
public class UserService {
  // user service code
}

然後我們編寫一個簡單的測試用例來測試這個配置:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/user-bean-config.xml");
UserService userService = context.getBean(UserService.class);
assertNotNull(userService);

4.3 基於 XML 的配置

最後,讓我們來了解一下基於 XML 的配置。這是 Spring 中配置 Bean 的傳統方式。

顯然,在這種方法中,我們將在 XML 配置文件中進行所有的 Bean 映射

因此,讓我們創建一個 XML 配置文件,account-bean-config.xml,併為我們的 AccountService 類定義 Bean:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd">
	  
  <bean id="accountService" class="com.baeldung.applicationcontext.AccountService">
    <constructor-arg name="accountRepository" ref="accountRepository" />
  </bean>
	
  <bean id="accountRepository" class="com.baeldung.applicationcontext.AccountRepository" />
</beans>

5. 應用上下文的類型

Spring 提供了不同類型的 ApplicationContext 容器,以滿足不同的需求。這些都是 ApplicationContext 接口的實現。下面我們來看看一些常見的 ApplicationContext 類型。

5.1. <em>AnnotationConfigApplicationContext</em>

首先,讓我們看看 <em>AnnotationConfigApplicationContext</em> 類,該類自 Spring 3.0 版本開始引入。它可以接受帶有 <strong>@Configuration</strong>、`@Component, 以及 JSR-330 元數據標註的作為輸入。

下面是一個使用 <em>AnnotationConfigApplicationContext</em> 容器的簡單示例,該示例使用了基於 Java 的配置:

ApplicationContext context = new AnnotationConfigApplicationContext(AccountConfig.class);
AccountService accountService = context.getBean(AccountService.class);

5.2. <em >AnnotationConfigWebApplicationContext</em>

`AnnotationConfigWebApplicationContext> 是 AnnotationConfigApplicationContext 的一種基於Web的變體。

我們可能使用此類來配置 Spring 的 ContextLoaderListener servlet 監聽器或 Spring MVC 的 DispatcherServletweb.xml 文件中。

此外,從 Spring 3.0 版本開始,我們也可以通過編程方式配置此應用程序上下文容器。 只需要實現 WebApplicationInitializer 接口即可。

public class MyWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    context.register(AccountConfig.class);
    context.setServletContext(container);

    // servlet configuration
  }
}

5.3. <em >XmlWebApplicationContext</em>

如果我們在 Web 應用程序中使用基於 XML 的配置,則可以使用 <em >XmlWebApplicationContext</em> 類。

事實上,配置此容器就像 <em >AnnotationConfigWebApplicationContext</em> 類一樣,這意味着我們可以通過 <em >web.xml</em > 或實現 `WebApplicationInitializer> 接口來配置它。

public class MyXmlWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    XmlWebApplicationContext context = new XmlWebApplicationContext();
    context.setConfigLocation("/WEB-INF/spring/applicationContext.xml");
    context.setServletContext(container);

    // Servlet configuration
  }
}

5.4. <em >FileSystemXMLApplicationContext</em >

我們使用 <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/support/FileSystemXmlApplicationContext.html"><em >FileSystemXMLApplicationContext</em ></a> 類來從文件系統或 URL 中加載基於 XML 的 Spring 配置文件。 此類在我們需要通過編程方式加載 <em >ApplicationContext</em > 時非常有用。 通常,測試套件和獨立應用程序是該類的潛在用例。

例如,讓我們看看如何創建 Spring 容器並加載 XML 配置文件中的 bean:

String path = "C:/myProject/src/main/resources/applicationcontext/account-bean-config.xml";

ApplicationContext context = new FileSystemXmlApplicationContext(path);
AccountService accountService = context.getBean("accountService", AccountService.class);

5.5. <em >ClassPathXmlApplicationContext</em ></a >

如果需要從類路徑加載 XML 配置文件,可以使用 <a href="https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/support/ClassPathXmlApplicationContext.html"><em >ClassPathXmlApplicationContext</em ></a >> 類。 類似於FileSystemXMLApplicationContext,它對測試套件以及嵌入在 JAR 文件中的應用程序上下文非常有用。

讓我們來看一個使用該類的示例:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/account-bean-config.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);

6. 在 Spring 中使用多個 ApplicationContext

此外,在單個應用程序中,也可能存在需要多個 ApplicationContext 實例的情況。

6.1. 模塊化應用

在大型模塊化應用中,每個模塊可能擁有自己的上下文。 這有助於隔離每個模塊的配置,防止 Bean 命名衝突,並簡化維護。

對於模塊化應用,每個模塊可以加載自己的 ApplicationContext

// Module 1 Context
ApplicationContext module1Context = new AnnotationConfigApplicationContext(Module1Config.class);

// Module 2 Context
ApplicationContext module2Context = new AnnotationConfigApplicationContext(Module2Config.class);

每個上下文可以獨立管理其 Bean,而無需干擾其他模塊上下文。

6.2. 層次化應用上下文

Spring 允許使用層次化上下文,其中父上下文可以定義可供所有子上下文使用的 Bean,但子上下文可以擁有特定於其模塊的 Bean。 這在例如在父上下文中擁有共享的核心配置的情況下非常有用。

以下是一個父子上下文的示例:

// Parent ApplicationContext
ApplicationContext parentContext = new AnnotationConfigApplicationContext(ParentConfig.class);

// Child ApplicationContext
AnnotationConfigApplicationContext childContext = new AnnotationConfigApplicationContext();
childContext.setParent(parentContext);
childContext.register(ChildConfig.class);
childContext.refresh();

在此示例中,parentContext 首先被加載。 childContext 被創建並使用 setParent() 方法與 parentContext 鏈接。 定義在 ParentConfig 中的 Bean 將在 childContext 中可用。

6.3. 測試隔離

我們可以使用不同的 <em >ApplicationContext</em> 實例來模擬應用程序的不同部分,以便在測試過程中進行。<strong >這允許您在不影響其他部分的情況下測試應用程序的一個部分。</strong>

對於單元測試或集成測試,我們可能需要為每個測試場景創建特定的上下文:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Module1Config.class })
public class TestClass1 {
    @Autowired
    ApplicationContext context1;

    // Test cases
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { Module2Config.class })
public class TestClass2 {
    @Autowired
    ApplicationContext context2;

    // Test cases
}

這確保測試類是隔離的,並且具有自己的上下文配置。

7. ApplicationContext 的附加功能

ApplicationContext 提供了以下附加功能:

  • Bean 掃描: 自動掃描項目中的所有 Bean 定義,包括 XML、註解和 Java 代碼。
  • 資源訪問: 方便地訪問項目中的各種資源,如配置文件、圖像、音頻等。
  • 事件發佈與訂閲: 支持事件發佈和訂閲機制,實現組件之間的鬆耦合。
  • AOP 支持: 提供對面向方面編程 (AOP) 的支持,允許在不修改源代碼的情況下增強應用程序的功能。
  • 事務管理: 簡化事務管理的流程,提高應用程序的可靠性。
  • JNDI 支持: 支持通過 JNDI 查找和訪問 Bean。

7.1. 消息解析

<em>ApplicationContext</em> 接口支持消息解析和國際化,通過擴展MessageSource 接口來實現。 此外,Spring 提供了兩個MessageSource 實現:`ResourceBundleMessageSourceStaticMessageSource

我們可以使用 <em>StaticMessageSource</em> 編程方式向源中添加消息;但是,它僅支持基本的國際化,更適合用於測試,而不是生產環境。

另一方面,<em>ResourceBundleMessageSource</em><em>MessageSource</em> 最常用的實現。 它依賴於 JDK 內置的 `ResouceBundle 實現。 它還使用 JDK 標準的消息解析,由 MessageFormat 提供。

現在讓我們看看如何使用 <em>MessageSource</em> 從 properties 文件中讀取消息。

首先,我們將 `messages.properties 文件放在類路徑上:

account.name=TestAccount

第二,我們將添加一個 Bean 定義到我們的 AccountConfig 類中:

@Bean
public MessageSource messageSource() {
  ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
  messageSource.setBasename("config/messages");
  return messageSource;
}

第三,我們將注入 MessageSourceAccountService 中:

@Autowired
private MessageSource messageSource;

最後,我們可以使用 getMessage 方法在 AccountService 中的任何地方讀取消息:

messageSource.getMessage("account.name", null, Locale.ENGLISH);

Spring 還提供了 ReloadableResourceBundleMessageSource 類,它允許從任何 Spring 資源位置讀取文件,並支持 bundle 屬性文件的熱重載。

7.2. 事件處理

<em>ApplicationContext</em> 通過使用 <em>ApplicationEvent</em> 類和 <em>ApplicationListener</em> 接口來支持事件處理。它內置了諸如 <em>ContextStartedEvent</em><em>ContextStoppedEvent</em><em>ContextClosedEvent</em><em>RequestHandledEvent</em> 等事件。此外,它還支持用於業務用例的自定義事件。

8. 結論

在本文中,我們探討了 Spring 中 ApplicationContext 容器的各個方面。我們還研究瞭如何配置 Spring bean 的不同示例。最後,我們學習瞭如何創建和使用不同類型的 ApplicationContext

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.