惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 时空穿越者

java并发:深入解析 ThreadPoolExecutor.addWorker() 流水线技术解析:处理器重排序的硬件基础 java并发:synchronized 揭秘 java并发:管道流(Piped Streams)的应用场景 java并发:再次认识一下Java中的锁 —— 类级别的锁是否存在? LangGraph:add_conditional_edges详解 Spring异步机制:@Async Spring BeanDefinition Spring Resource Spring之BeanFactory:解析getBean()方法 Spring之IoC容器 Spring的整体架构 Spring Data JPA:解析CriteriaQuery Spring Data JPA:解析CriteriaBuilder Spring Data JPA:解析JpaSpecificationExecutor & Specification Spring Data JPA:解析SimpleJpaRepository java并发:线程池之Executors(ScheduledExecutorService篇) - 时空穿越者 java并发:线程池之饱和策略 java并发:线程池之ThreadPoolExecutor
Spring之ApplicationContext
时空穿越者 · 2021-09-05 · via 博客园 - 时空穿越者

ApplicationContext

ApplicationContext是Spring的高级容器。

与BeanFactory类似,它可以加载bean定义并根据请求分发bean;此外,它还添加了很多特定的功能,比如:从属性文件解析文本消息、将应用程序事件发布到感兴趣的事件侦听器。

定义

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
        MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

方法

类图

Spring提供了适合不同需求的ApplicationContext,每个应用程序上下文可以拥有多个配置文件、配置类或两者的混合,相关类图见下图:

ConfigurableApplicationContext

解读:

ConfigurableApplicationContext 扩展自 ApplicationContext,新增了 reflesh() 和 close() 这两个方法,使得其具有启动、刷新和关闭应用上下文的能力:

(1)在应用上下文关闭的情况下调用 reflesh() 即可启动应用上下文;在应用上下文启动的情况下调用 reflesh() 即可清除缓存并且重新装载配置信息;

(2)调用 close() 方法则可以关闭应用上下文。 

补充:

AbstractApplicationContext 等子类实现了 reflesh() 方法

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的Spring配置文件。

应用代码如下:

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为主线。

ConfigurableWebApplicationContext

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
  }
}

Spring boot相关

深度解析

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:

(1)BeanFactory 在初始化容器时并未实例化 Bean,直到第一次访问某个Bean 时才实例化目标 Bean;

(2)ApplicationContext 在初始化容器时就实例化所有的单实例 Bean。