首页 > 编程语言 >Spring源码系列(补充):详解ApplicationContext

Spring源码系列(补充):详解ApplicationContext

时间:2023-04-21 13:58:28浏览次数:30  
标签:ApplicationContext applicationContext Spring System 源码 println message out

前言

在之前的文章中,我们已经对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框架,加深对其理解和掌握。
公众号

标签:ApplicationContext,applicationContext,Spring,System,源码,println,message,out
From: https://www.cnblogs.com/guoxiaoyu/p/17340082.html

相关文章

  • 使用Oracle的springBoot
    application.ymlspring:application:name:zplatformdatasource:driver-class-name:oracle.jdbc.driver.OracleDriverurl:jdbc:oracle:thin:@主机号:端口号/数据库?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetriev......
  • 在idea中查看源码时 download source failed的处理办法
    检查ideamaven配置切换路径BuildTools->Maven->Importing勾选前两个执行maven命令:mvndependency:resolve-Dclassifier=sources执行完后,再次打开源码类就能看到源码了。......
  • xHook 源码解析
    xHook是爱奇艺开源的一个PLTHook框架项目地址:https://github.com/iqiyi/xHook该项目实现了PTL/GOTHookPTLhook的本质是修改内存中,PLT表对应的值,来实现跳转到自定义函数的.got和.plt它们的具体含义。TheGlobalOffsetTable(GOT)。简单来说就是在数据段的地址表......
  • 启动springboot项目指定jdk版本以及设置控制台中文
    代码:@echoofftitle=javaServerchcp936setJAVA_HOME=D:\Tools\JDK8setPATH=%JAVA_HOME%\bin;%JAVA_HOME%\jre\binsetCLASSPATH=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;lib/run.jarjava-Dfile.encoding=GBK-Xms64m-Xmx1000......
  • Spring 自定义属性编辑器
    装Spring自定义属性编辑器 SpringDI注入的时候可以把普通属性注入进来,但是像Date类型的就无法被识别。这时可以通过Spring的属性编辑器把配置文件中的字符串转化成相应的对象进行注入。Spring有自带的属性编辑器,我们也可以写自定义的属性编辑器 自定义属性编辑器:继承java.bean......
  • springmvc 链接数据库错误
    1.Causedby:org.xml.sax.SAXParseException:cos-all-limited.1.2:An''all''modelgroupmustappearinaparticlewith'{'minoccurs'}'='{'maxoccurs'}'=1,andthatparticlemustbepartofapa......
  • vue2源码-十一、Vue的生命周期
    Vue的生命周期钩子函数是如何实现?内部利用一个发布订阅模式,将用户写的钩子维护成一个数组,后续依次调用hooks。主要靠的是mergerOptions方法有哪些?引用自https://vue3js.cn/interview/vue/lifecycle.html#%E4%BA%8C%E3%80%81%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E6%9C%......
  • 【Spring】@Configuration为什么会生成代理呢?
    1 前言首先说下为什么会产生这样的疑惑哈,最近在看Spring-retry的时候,发现:其次我们再来看个现象,@Component声明了一个Bean,内部有个单例AService,当我们调用两次 aService()发现得到的对象不一样:@ComponentpublicclassDemo{publicclassAService{publ......
  • vue3 源码
     这文章写的很好 Compiler模块:编译模板系统。主要职责是将template编译成虚拟节点。Runtime模块:也可以称之为Renderer模块,真正负责渲染的模块。主要职责是将虚拟节点渲染成真实元素,然后显示到浏览器上。Reactivity模块:响应式系统。主要职责是监听响应式的数据,然后通过di......
  • 苞米豆的多数据源 → dynamic-datasource-spring-boot-starter,挺香的!
    开心一刻2023年元旦,我妈又开始了对我的念叨妈:你到底想多少岁结婚我:60妈:60,你想找个多大的我:找个55的啊,她55我60,结婚都有退休金,不用上班不用生孩子,不用买车买房,成天就是玩儿我:而且一结婚就是白头偕老,多好我妈直接一大嘴巴子呼我脸上需求背景......