Spring之ApplicationContext


ApplicationContext

ApplicationContext是Spring的高級容器。

與BeanFactory類似,它可以加載bean定義並根據請求分發bean;此外,它還添加了很多特定的功能,比如:從屬性文件解析文本消息、將應用程序事件發布到感興趣的事件偵聽器。

類圖

可以使用如下代碼創建ApplicationContext:

ApplicationContext context = new FileSystemXmlApplicationContext("Beans.xml");

Spring提供了適合不同需求的ApplicationContext,每個應用程序上下文可以擁有多個配置文件、配置類或兩者的混合,相關類圖見下圖:

解讀:

  • ConfigurableApplicationContext

ConfigurableApplicationContext 擴展自 ApplicationContext,新增了兩個主要方法 reflesh() 和close(),使得其具有啟動、刷新和關閉應用上下文的能力。

在應用上下文關閉的情況下調用 reflesh() 即可啟動應用上下文;在應用上下文啟動的情況下調用 reflesh() 即可清除緩存並且重新裝載配置信息;調用 close() 方法則可以關閉應用上下文。 

ApplicationContext實現類

普通應用

FileSystemXMLApplicationContext

通過FileSystemXMLApplicationContext[地址]可以從文件系統或url加載基於xml的Spring配置文件。

應用代碼如下:

String path = "D:/source/Test/src/main/resources/applicationcontext/bean-config.xml";

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

 

ClassPathXmlApplicationContext

通過ClassPathXmlApplicationContext[地址]可以從類路徑加載XML配置文件。

應用代碼如下:

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

 

AnnotationConfigApplicationContext

AnnotationConfigApplicationContext是在Spring 3.0中引入的(與@Configuration、@Component和JSR-330元數據注釋等一起工作)。

應用代碼如下:

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

 

Web應用

進一步發掘,可以得到如下類圖:

解讀:

觀察其與本文前面展示的類圖之間的區別,可以發現Web應用以WebApplicationContext為主線。

 

AnnotationConfigWebApplicationContext

AnnotationConfigWebApplicationContext是AnnotationConfigApplicationContext的一個基於web的變體。

Note:

從Spring 3.0開始,可以通過編程方式配置ApplicationContext,開發人員需要做的是實現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
  }
}

 

XmlWebApplicationContext

如果在web應用程序中使用基於XML的配置可以使用XmlWebApplicationContext;類似AnnotationConfigWebApplicationContext,可以通過實現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
  }
}

 

深度解析

Message Resolution

ApplicationContext接口通過擴展MessageSource接口來支持消息解析和國際化。

 

Spring提供了兩個MessageSource實現:ResourceBundleMessageSource、StaticMessageSource。

  • StaticMessageSource

可以使用StaticMessageSource以編程方式向源添加消息,它支持基本的國際化,更適合測試而不是生產環境。

  • ResourceBundleMessageSource

ResourceBundleMessageSource是MessageSource最常見的實現,它依賴於底層JDK的ResouceBundle[地址]實現;它還使用了 JDK 提供的標准消息解析 —— MessageFormat。

案例:

@Bean
public MessageSource messageSource() {
  ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
  messageSource.setBasename("config/messages");
  return messageSource;
}
@Autowired
private MessageSource messageSource;
messageSource.getMessage("account.name", null, Locale.ENGLISH);

 

Note:

Spring提供了ReloadableResourceBundleMessageSource類[地址],它允許從任何Spring資源位置讀取文件,並支持熱加載bundle屬性文件。

 

Event Handling

ApplicationContext 通過擴展ApplicationEventPublisher讓容器擁有發布應用上下文事件的能力;它支持內置事件,如:ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent;此外,它還支持自定義事件。

ApplicationContext 在 ApplicationEvent 類和 ApplicationListener 接口的幫助下支持事件處理:

  • 實現了 ApplicationListener 接口的 Bean 可以接收到容器事件,進而對事件進行處理
  • 在 ApplicationContext 的子類 AbstractApplicationContext 中存在一個 ApplicationEventMulticaster 變量,它保存所有監聽器,以便在容器產生上下文事件時通知這些事件監聽器

 

ApplicationContext層次結構

ApplicationContext的層次結構提供了一種重用bean的方法,可以在child ApplicationContext中訪問在parent ApplicationContext中定義的bean。

Spring提供了指定parent ApplicationContext的方法,相關構造函數如下:

 

Note:

child ApplicationContext與parent ApplicationContext通過父/子關系相關聯;不是組合關系。

對這一概念的理解,請琢磨下面幾個case:

場景1:

Each Spring MVC webapp has one root application context and one servlet application context for each DispatcherServlet.

The root application context is the parent of each servlet application context.

Beans defined in "contextConfigLocation" (context-param in web.xml) are loaded into root application context.

Beans in <servlet-name>-servlet.xml are loaded into servlet application context.

If an EAR has multiple web apps, an EAR level application context can parent the root context of each webapp in the EAR.

資料

https://docs.spring.io/spring-framework/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-servlet


場景2:

For example, Spring Security is independent of Spring MVC and requires its configuration beans to go in the webapp context. If you want to use Spring MVC with it, then the config for that has to go into the servlet context, which has the root webapp context as its parent.


場景3:

It's possible to create separate contexts and organize them in a hierarchy in Spring Boot.

Each child context can override configuration inherited from the parent context.

The SpringApplicationBuilder class provides a fluent API to create a parent-child relationship between contexts using parent()child() and sibling() methods.

資料:

https://www.baeldung.com/spring-boot-context-hierarchy

 

Note:

BeanFactory 在初始化容器時並未實例化 Bean,直到第一次訪問某個Bean 時才實例化目標 Bean;ApplicationContext 在初始化容器時就實例化所有的單實例 Bean。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM