Spring源码系列(补充):详解ApplicationContext
前言
在之前的文章中,我们已经对Spring源码中的一些核心概念进行了分析。由于篇幅限制,我们并没有详细解释ApplicationContext类所继承的父接口及其作用。因此,本文将单独为ApplicationContext进行详细说明,包括其继承的父接口及其作用。
ApplicationContext父接口
MessageSource
大家应该都比较熟悉MessageSource,它用于国际化,许多项目都会使用它。使用MessageSource的基本步骤如下:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
String message = applicationContext.getMessage("test", null, new Locale("en"));
System.out.println(message);
你需要在resources路径下创建相应的语言文件。例如,在本文的代码示例中,我们使用了“en”语言,因此需要创建messages_en.properties文件,其内容如下:
test=b
这样,当我们获取“test”语言时,就会得到“b”。
ResourcePatternResolver
ResourcePatternResolver主要用于获取资源,即资源加载,可以加载某个文件的内容。具体步骤如下:
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// String message = applicationContext.getMessage("test", null, new Locale("en"));
// System.out.println(message);
Resource resource = applicationContext.getResource("classpath:spring.properties");
System.out.println(resource.contentLength());
除此之外,ResourcePatternResolver还有其他用法,例如:
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
// String message = applicationContext.getMessage("test", null, new Locale("en"));
// System.out.println(message);
Resource resource = applicationContext.getResource("https://www.baidu.com");
System.out.println(resource.contentLength());
System.out.println(resource.getURL());
//还可以获取多个资源
Resource[] resources = applicationContext.getResources("classpath:com/xiaoyu/*.class");
Arrays.stream(resources).forEach(System.out::println);
以上只是简单的示例,具体使用方法还需根据实际情况进行调整。
EnvironmentCapable
获取运行时环境可以使用ApplicationContext的getEnvironment方法,具体用法如下:
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
applicationContext.getEnvironment().getPropertySources().forEach(System.out::println);
System.out.println("================");
applicationContext.getEnvironment().getSystemEnvironment().forEach((k, v) -> System.out.println(k + " : " + v));
System.out.println("================");
applicationContext.getEnvironment().getSystemProperties().forEach((k, v) -> System.out.println(k + " : " + v));
System.out.println("================");
System.out.println(applicationContext.getEnvironment().getProperty("sun.jnu.encoding"));
System.out.println(applicationContext.getEnvironment().getProperty("xiaoyu"));
@PropertySource("classpath:spring.properties")
注意,可以使用@PropertySource注解将spring.properties添加到运行时环境,然后通过getProperty方法去获取。
ApplicationEventPublisher
ApplicationEventPublisher是一个事件发布器,我们可以通过ApplicationContext来发布一个相应的事件,具体步骤如下:
// 创建一个Spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
//发布自己的事件
applicationContext.publishEvent(new MyEvent("xiaoyu"));
定义自己的事件:
public class MyEvent extends ApplicationEvent {
private String message;
public MyEvent(String message) {
super(message);
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
创建一个事件监听器,可以监听所有事件,也可以单独监听自己的事件。如果想要监听所有事件,直接去掉泛型即可。Spring的事件也可以监听到,因此在监听部分需要自己判断是什么事件。具体步骤如下:
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
/**
* Handle an application event.
*
* @param event the event to respond to
*/
@Override
public void onApplicationEvent(MyEvent event) {
if (event instanceof MyEvent) {
System.out.println(((MyEvent) event).getMessage());
}
System.out.println(event);
}
}
OrderComparator
这里注意下,OrderComparator并不是ApplicationContext的父接口,它是Spring内部提供的一种比较器,用于排序实现了Order接口或者@Order注解的bean。虽然在工作中我们也会用到排序,但单独写一篇文章可能并不必要,因此在这里简单提一下。
他是Spring内部提供的一种比较器,用于排序实现了order接口或者@order注解,首先定义两个具体的bean,具体用法如下:
public class First implements Ordered {
@Override
public int getOrder() {
return 1;
}
}
public class Second implements Ordered {
@Override
public int getOrder() {
return 2;
}
}
First first = new First();
Second second = new Second();
Arrays.asList(first, second).stream().sorted(OrderComparator.INSTANCE).forEach(System.out::println);
这样就会升序排序,数值越小越在前面,如果使用的是注解形式的@order,则使用下面的实例:
First first = new First();
Second second = new Second();
Arrays.asList(first, second).stream().sorted(AnnotationAwareOrderComparator.INSTANCE).forEach(System.out::println);
注意,OrderComparator只适用于实现了Ordered接口或者@Order注解的bean,如果需要对其他类型的对象进行排序,可以使用其他比较器。
结语
至此,Spring的核心概念解析告一段落,但这只是一个开始,后续我们将深入理解Spring的源码。因此,建议仔细查看Spring的核心关键类,对于后续查看Spring源码会非常有帮助。同时,在实际项目中多关注Spring框架,加深对其理解和掌握。

Spring源码系列(补充):详解ApplicationContext的更多相关文章
- Spring源码系列(一)--详解介绍bean组件
简介 spring-bean 组件是 IoC 的核心,我们可以通过BeanFactory来获取所需的对象,对象的实例化.属性装配和初始化都可以交给 spring 来管理. 针对 spring-bean ...
- Spring Boot源码中模块详解
Spring Boot源码中模块详解 一.源码 spring boot2.1版本源码地址:https://github.com/spring-projects/spring-boot/tree/2.1 ...
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- Spring源码系列 — BeanDefinition
一.前言 回顾 在Spring源码系列第二篇中介绍了Environment组件,后续又介绍Spring中Resource的抽象,但是对于上下文的启动过程详解并未继续.经过一个星期的准备,梳理了Spri ...
- Spring源码系列(四)--spring-aop是如何设计的
简介 spring-aop 用于生成动态代理类(底层是使用 JDK 动态代理或 cglib 来生成代理类),搭配 spring-bean 一起使用,可以使 AOP 更加解耦.方便.在实际项目中,spr ...
- 事件机制-Spring 源码系列(4)
事件机制-Spring 源码系列(4) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcess ...
- Spring源码系列 — 注解原理
前言 前文中主要介绍了Spring中处理BeanDefinition的扩展点,其中着重介绍BeanDefinitionParser方式的扩展.本篇文章承接该内容,详解Spring中如何利用BeanDe ...
- Spring源码系列 — BeanDefinition扩展点
前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition ...
- Ioc容器依赖注入-Spring 源码系列(2)
Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...
- Ioc容器BeanPostProcessor-Spring 源码系列(3)
Ioc容器BeanPostProcessor-Spring 源码系列(3) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Io ...
随机推荐
- django_应用及分布式路由
一.应用的定义 1.应用在Django中是一个独立的业务模块,可以包含自己的路由.视图.模板.模型. 例如如下图所示,一个资讯类网站中会有不同的模块,如果所有的模块共用一个views.py文件,则会导 ...
- 【Rust入门】(一)构建自己的第一个Rust项目
安装Rust 参考文档,指定安装目录和镜像配置. rustc --version 检查是否安装成功. 构建程序 使用rustc编译运行 rustc 编译:rustc main.js 运行: Windo ...
- Openssl自签证书|Nginx配置全站HTTPS,包括WSS(websocket)
一.生成自签证书 如果有购买证书的,可忽略此步骤. 生成方法一: openssl genrsa -des3 -out ca.key 1024 openssl rsa -in ca.key -out c ...
- python requests 上传文件_python3使用requests上传文件,content-type踩的坑
通常提交普通表单时,requests的post方法可以指定headers,所以我在使用requests模拟上传文件行为时,直接按照下面的方式写了: 然后服务器就报出了找不到分隔符Invalid mul ...
- OSPF之路由过载overflower 及GR(Graceful Restart优雅重起)
- 网络如何运作——详细DNS、HTTP、网站
详细的DNS 什么是DNS? DNS(域名系统)为我们提供了一种简单的方式来与互联网上的设备进行通信,而无需记住复杂的数字.就像每个房子都有一个唯一的地址可以直接向它发送邮件一样,互联网上的每台计算机 ...
- Java笔记第五弹
编码表 将字符存储到计算机中----编码:反之,则为解码: GBK编码:最常用的中文码表 GB18030--最新的中文码表 Unicode字符集:业界的一种标准,也称为统一码.万国码 UTF-8编码: ...
- Javaweb实践复习--MyBatis
增删改查操作 查询 查询所有数据 1.编写接口方法:Mapper接口------参数:无------结果:List 2.编写sql语句:SQL映射文件 一般情况下,若是用户实体类里面的变量名称与数据库 ...
- 安装node.js教程------深入使用Vue
教程 1.下载nodejs引擎 网址:https://nodejs.org/en/download/ 选择32-bit或者64-bit都行 2.下载最新版npm.zip压缩包 网址:http://no ...
- ctfshow VIP限免题目(最新)
源码泄露 这一题主要考察如何查看网页源代码,查看方式主要有三种 在网页前面加上view-source: 右键页面,点击查看页面源代码 键盘上按下F12打开开发者工具,在查看器中查看源代码 这一题随便一 ...