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

打印 上一主题 下一主题

主题 945|帖子 945|积分 2835

前言

在之前的文章中,我们已经对Spring源码中的一些核心概念进行了分析。由于篇幅限制,我们并没有详细解释ApplicationContext类所继承的父接口及其作用。因此,本文将单独为ApplicationContext进行详细说明,包括其继承的父接口及其作用。
ApplicationContext父接口

MessageSource

大家应该都比较熟悉MessageSource,它用于国际化,许多项目都会使用它。使用MessageSource的基本步骤如下:
  1. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  2. String message = applicationContext.getMessage("test", null, new Locale("en"));
  3. System.out.println(message);
复制代码
你需要在resources路径下创建相应的语言文件。例如,在本文的代码示例中,我们使用了“en”语言,因此需要创建messages_en.properties文件,其内容如下:
  1. test=b
复制代码
这样,当我们获取“test”语言时,就会得到“b”。
ResourcePatternResolver

ResourcePatternResolver主要用于获取资源,即资源加载,可以加载某个文件的内容。具体步骤如下:
  1. // 创建一个Spring容器
  2.                 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  3. //                String message = applicationContext.getMessage("test", null, new Locale("en"));
  4. //                System.out.println(message);
  5.                 Resource resource = applicationContext.getResource("classpath:spring.properties");
  6.                 System.out.println(resource.contentLength());
复制代码
除此之外,ResourcePatternResolver还有其他用法,例如:
  1. // 创建一个Spring容器
  2.                 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  3. //                String message = applicationContext.getMessage("test", null, new Locale("en"));
  4. //                System.out.println(message);
  5.                 Resource resource = applicationContext.getResource("https://www.baidu.com");
  6.                 System.out.println(resource.contentLength());
  7.                 System.out.println(resource.getURL());
  8.                 //还可以获取多个资源
  9.                 Resource[] resources = applicationContext.getResources("classpath:com/xiaoyu/*.class");
  10.                 Arrays.stream(resources).forEach(System.out::println);
复制代码
以上只是简单的示例,具体使用方法还需根据实际情况进行调整。
EnvironmentCapable

获取运行时环境可以使用ApplicationContext的getEnvironment方法,具体用法如下:
  1. // 创建一个Spring容器
  2.                 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  3.                 applicationContext.getEnvironment().getPropertySources().forEach(System.out::println);
  4.                 System.out.println("================");
  5.                 applicationContext.getEnvironment().getSystemEnvironment().forEach((k, v) -> System.out.println(k + " : " + v));
  6.                 System.out.println("================");
  7.                 applicationContext.getEnvironment().getSystemProperties().forEach((k, v) -> System.out.println(k + " : " + v));
  8.                 System.out.println("================");
  9.                 System.out.println(applicationContext.getEnvironment().getProperty("sun.jnu.encoding"));
  10.                 System.out.println(applicationContext.getEnvironment().getProperty("xiaoyu"));
复制代码
  1. @PropertySource("classpath:spring.properties")
复制代码
注意,可以使用@PropertySource注解将spring.properties添加到运行时环境,然后通过getProperty方法去获取。
ApplicationEventPublisher

ApplicationEventPublisher是一个事件发布器,我们可以通过ApplicationContext来发布一个相应的事件,具体步骤如下:
  1. // 创建一个Spring容器
  2.                 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  3.     //发布自己的事件
  4.                 applicationContext.publishEvent(new MyEvent("xiaoyu"));
复制代码
定义自己的事件:
  1. public class MyEvent extends ApplicationEvent {
  2.         private String message;
  3.         public MyEvent(String message) {
  4.                 super(message);
  5.                 this.message = message;
  6.         }
  7.         public String getMessage() {
  8.                 return message;
  9.         }
  10.         public void setMessage(String message) {
  11.                 this.message = message;
  12.         }
  13. }
复制代码
创建一个事件监听器,可以监听所有事件,也可以单独监听自己的事件。如果想要监听所有事件,直接去掉泛型即可。Spring的事件也可以监听到,因此在监听部分需要自己判断是什么事件。具体步骤如下:
  1. @Component
  2. public class MyEventListener implements ApplicationListener<MyEvent> {
  3.         /**
  4.          * Handle an application event.
  5.          *
  6.          * @param event the event to respond to
  7.          */
  8.         @Override
  9.         public void onApplicationEvent(MyEvent event) {
  10.                 if (event instanceof MyEvent) {
  11.                         System.out.println(((MyEvent) event).getMessage());
  12.                 }
  13.                 System.out.println(event);
  14.         }
  15. }
复制代码
OrderComparator

这里注意下,OrderComparator并不是ApplicationContext的父接口,它是Spring内部提供的一种比较器,用于排序实现了Order接口或者@Order注解的bean。虽然在工作中我们也会用到排序,但单独写一篇文章可能并不必要,因此在这里简单提一下。
他是Spring内部提供的一种比较器,用于排序实现了order接口或者@order注解,首先定义两个具体的bean,具体用法如下:
  1. public class First implements Ordered {
  2.         @Override
  3.         public int getOrder() {
  4.                 return 1;
  5.         }
  6. }
复制代码
  1. public class Second implements Ordered {
  2.         @Override
  3.         public int getOrder() {
  4.                 return 2;
  5.         }
  6. }
复制代码
  1. First first = new First();
  2.                 Second second = new Second();
  3.                 Arrays.asList(first, second).stream().sorted(OrderComparator.INSTANCE).forEach(System.out::println);
复制代码
这样就会升序排序,数值越小越在前面,如果使用的是注解形式的@order,则使用下面的实例:
  1. First first = new First();
  2.                 Second second = new Second();
  3.                 Arrays.asList(first, second).stream().sorted(AnnotationAwareOrderComparator.INSTANCE).forEach(System.out::println);
复制代码
注意,OrderComparator只适用于实现了Ordered接口或者@Order注解的bean,如果需要对其他类型的对象进行排序,可以使用其他比较器。
结语

至此,Spring的核心概念解析告一段落,但这只是一个开始,后续我们将深入理解Spring的源码。因此,建议仔细查看Spring的核心关键类,对于后续查看Spring源码会非常有帮助。同时,在实际项目中多关注Spring框架,加深对其理解和掌握。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

慢吞云雾缓吐愁

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表