[Java/Spring] 深入理解 : Spring 的 BeanFactory / ApplicationContext、Environment、PropertySource 、MessageSource 、ResourcePatternResolver的关系
1 辨析
PropertySource
PropertySource
: 解析环境资源及配置的底层组件
org.springframework.core.env.PropertyResolver
Environment
Environment
: 管理环境的配置与资源
org.springframework.core.env.Environment
- 其继承接口 PropertyResolver 属性解析器,用来解析不同属性源 PropertySource 里的 key-value。
org.springframework.core.env.AbstractEnvironment implements ConfigurableEnvironment
- 实现子类 :
- org.springframework.core.env.StandardEnvironment extends AbstractEnvironment
- org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment extends StandardEnvironment implements ConfigurableReactiveWebEnvironment
- org.springframework.web.context.support.StandardServletEnvironment extends StandardEnvironment implements ConfigurableWebEnvironment
- 内部属性 :
private final Set<String> activeProfiles = new LinkedHashSet<>();
private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());
private final MutablePropertySources propertySources = new MutablePropertySources();
private final ConfigurablePropertyResolver propertyResolver = new PropertySourcesPropertyResolver(this.propertySources);
- 与 environment 关系
Environment -> ConfigurableEnvironment -> AbstractEnvironment -> StandardEnvironment -> StandardReactiveWebEnvironment: 父子层次
ConfigurableEnvironment -> MutablePropertySources: 获取可变多个配置源 ( ConfigurableEnvironment#getPropertySources() )
MutablePropertySources extends PropertySources ( PropertySources extends Iterable<PropertySource<?>> ) : 包含多个 PropertySource
BeanFactory
BeanFactory
: Spring IOC 容器的顶级抽象接口
org.springframework.beans.factory.BeanFactory
- BeanFactory 中 Bean 的生命周期
- 2个重要的后置处理器: BeanFactoryPostProcessor、BeanPostProcessor
ApplicationContext
- ApplicationContext : Spring IOC 容器的默认实现、基于 Environment 创建 上下文、跨语言/地区支持、应用事件发布支持、
org.springframework.context.ApplicationContext
ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver
org.springframework.context.support.AbstractApplicationContext
ApplicationContext
本质是一个维护 Bean 定义以及对象之间协作关系的接口,或者说为应用 application 提供配置的核心接口。
1、Bean 容器(
ListableBeanFactory
/HierarchicalBeanFactory
).ApplicationContext 继承 ListableBeanFactory 和 HierarchicalBeanFactory ,实现了 Bean 的生命周期管理(BeanFactoy)、有序性(ListableBeanFactory)和层次性(HierarchicalBeanFactory),并进行扩展。
Spring也为我们提供了 ApplicationContext 的多种类型的容器实现,供我们在不同的应用场景选择。例如:AnnotationConfigApplicationContext:从一个或多个基于 Java 的配置类中加载上下文定义,适用于 Java 注解的方式
AnnotationConfigWebApplicationContext:专门为 web 应用准备的,适用于注解方式
2、ApplicationContext 继承 EnvironmentCapable 接口:
带有Capable后缀的接口在Spring中带有getXXX的含义,也就是实现了这个接口,就可以通过该接口的实例获取到XXX,这个和Aware接口很类似
换言之,通过 ApplicationContext 可获得 Environment 对象。
所有的Spring应用上下文都实现了 EnvironmentCapable 接口, 这个接口主要用于检查接受了 BeanFactory 接口的框架方法,不管这些接口是不是 ApplicationContext ,为了与 environment 交互,如果这些接口确实是可用的。
例如:(new ClassPathXmlApplicationContext("bean.xml") ).getEnvironment().getProperty("key");
在 Spring Boot 的启动方法 run() 我们可以看到 Spring Boot 根据当前应用环境 webApplicationType 决定创建相应的 ConfigurableApplicationContext 对象
run() 内的prepareEnvironment
监听 ApplicationEnvironmentPreparedEvent 事件,由 listeners 处理,然后 createApplicationContext() 创建上下文
3、跨语言/地区支持(
MessageSource
)
4、应用事件发布支持(
ApplicationEventPublisher
)
5、资源模式解析支持(
ResourcePatternResolver
)
MessageSource
MessageSource
org.springframework.context.MessageSource;
public interface MessageSource {
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
Use Demo
code = "application.version";
Locale locale = getUserLocale(httpRequest); // Locale对象标定了当前使用哪种语言
text = messageSource.getMessage(code, locale);
ApplicationEventPublisher
ApplicationEventPublisher
: 应用事件发布支持
public interface ApplicationEventPublisher {
default void publishEvent(ApplicationEvent event) {
publishEvent((Object) event);
}
void publishEvent(Object event);
}
事件发布是一种编程模式,是回调编程的一个变种。具体而言,就是我们可以在Spring上发布一个事件,然后Spring会寻找这个容器的监听器,然后调用监听器的代码。
例如,Spring 应用关闭后,会发布一个应用关闭事件。 应用代码可以注册这个事件的监听器, 处理一些资源关闭事件。
但这个模式最强的地方在于,它能把业务逻辑流程高度抽象起来,然后在这些抽象的流程中间插入事件发布。例如一个订单业务,遵循下单-付款-发货-收货,即可以抽象出对应的事件,如果我们想在用户下单时,弹出一些优惠提示,我们就可以注册一个下单事件的监听器来进行这个工作。一旦优惠截止,只需要卸载这个监听器即可。
事件流描述了一个应用逻辑流程的生命周期各个重要的节点。
所以经常的,当你发现只要是涉及生命周期这个话题时,事件出镜率总是非常高。
事实上,对于这个模式强编码出类似于"publish"和"event"的描述,确实有些过度抽象的嫌疑。
ResourcePatternResolver
ResourcePatternResolver
: 资源模式解析器
一个
ResourcePatternResolver
是一个ResourceLoader
。但前者比后者比多一个模式匹配的接口。通常,我们认为一个资源位置字符串代表了一个资源,但一个模式字符串可以匹配多个资源。
Resource[] getResources(String locationPattern) throws IOException;
所谓资源,在java的定义中,是一段字节流。文件是一段命名字节流,网络消息是一段字节流,内存是一块大字节数组……诸如此类,Resource接口抽象出这些来源,提供共同的操作接口。即从应用代码的角度出发,你不再需要管它是一个File还是一个URI,只需要老实调用getInputStream()或readableChannel()方法就可以了。
Spring的配置文件就是通过ResourcePatternResolver
读取的。触类旁通,你当然也可以通过它来获得你想要的文件,无论它在classpath下、一个本地文件还是一个网络位置。
2 Spring Framework 模块
重点关注:模块间的依赖关系
X 参考文献
- Spring environment 和 applicationContext - 博客园
- spring environment_Spring 中的 ApplicationContext - CSDN 【推荐】

本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!