ApplicationContext作为资源加载器;ApplicationContext作为事件发布者;

  Java原生提供了事件发布机制------EventObject对象作为发布的事件,EventListener作为处理发布事件的监听器。但是其并没有提供发布者的角色来桥接EventObject和EventListener。Spring对java原生的事件发布机制做了扩展:一方面扩展了EventObject和EventListener,使其可以记录事件发布时间,扩展了事件发布接口;更重要的一点,ApplicationContext自身可以充当事件发布者(因为其实现了ApplicationEventPublisher接口),完成了本应该由开发者来实现的代码(如果使用java原生发布事件机制的话)。当对象A(被观察者)发生变化时,有一个发布者(可以是被观察者自身,也可以委托第三方如spring容器)发出通知,事物B(观察者)能够收到通知更新自己的状态。这个就是经常使用到的观察者模式,spring容器提供了这种观察者模式的支持。我们通过一个例子来说明如何在Spring框架中使用事件发布,并能让观察者(listener)得到消息。首先,自定义我们的EventObject,作为发布者和监听者之间约定好的事件对象。

public class MyEvent extends ApplicationEvent {

    /**
*
*/
private static final long serialVersionUID = 1L; /**
* @param source
*/
public MyEvent(Object source){
super(source);
// TODO Auto-generated constructor stub
} }

自定义的MyEvent继承了ApplicationEvent,ApplicationEvent类是spring框架继承EventObject而来,加入了获取发布时间的方法。其次,自定义我们的EventListener,它负责监听容器发布的ApplicationEvent事件并进行处理:

public class MyListener implements ApplicationListener {

    /* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof MyEvent) {
System.out.println(event == null ? "" : event.getSource());
}
} }

因为我们只关心MyEvent事件的发布,所以在onApplicationEvent方法中进行了判断,过滤其他不相关发布事件。定义完了事件和监听器,基本就剩下发布事件的代码了。发布者由ApplicationContext来充当:

public class TestPublisher {
public static void main ( String args[] ) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml"); // applicationContext.xml配置文件中已经配置好了监听器
ctx.publishEvent(new MyEvent("Hello World")); // 发布事件,监听器接收到事件消息
}
}

最后,不要忘记在配置文件中添加监听对象:

<bean class="com.alibaba.china.publisher.MyListener" />

spring容器会自动加载配置文件中所有的ApplicationListener对象,把它注册到观察者列表中。当有事件发布的时候,就从这个观察者列表中挨个通知事件发布。程序执行结果如下:

其他细节点:

  1. ApplicationContext自动加载所有的Bean ApplicationContext自动加载所有的Bean;
  2. ApplicationContext自动识别BeanFactoryPostProcessor,BeanPostProcessor,并注册到容器中。

  ApplicationContext自动加载所有的Bean:ApplicationContext相对于BeanFactory不同的一点是,BeanFactory在用到Bean的时候才会去加载bean(在beanFactory.getBean(“beanName”)之前不会加载beanName的对象)。而ApplicationContext不同,在容器创建时就已经把所有的Bean加载进容器了。

  ApplicationContext自动识别BeanFactoryPostProcessor,BeanPostProcessor,并注册到容器中:BeanFactoryPostProcessor是容器在加载完BeanDefinition之后,容器初始化之前对beanFactory做处理的一个扩展机制。比如我们的antx配置项替换类PropertyPlaceholderConfigurer。我们只需要在配置文件中声明PropertyPlaceholderConfigurer这类BeanFactoryPostProcessor对象,ApplicationContext就能够识别出来并自动将这些processor注册到容器中。BeanPostProcessor也是同样的道理,ApplicationContext能够自动识别xml中配置好的这类bean并进行容器的注册。BeanFactory就不能这么简洁了,必须我们手动去把那些BeanFactoryPostProcessor以及BeanPostProcessor对象注册到容器中。ApplicationContext能够自己感知到这些processor,我们的工作只是去实现自定义的(或者直接使用spring已经实现了的)BeanFactoryPostProcessor和BeanPostProcessor,并在配置文件中声明。是不是觉得很神奇?ApplicationContext能做到感知的原因就在于其对mdb(Merged BeanDefinition)的处理。

org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory)实现:

// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// beanFactory的getBeanNamesForType方法能够根据对象的类型(此处是BeanFactoryPostProcessor.class),从mdb中找到他们的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
......
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
Collections.sort(priorityOrderedPostProcessors, new OrderComparator());
// 这里所有声明在配置文件中的BeanFactoryPostProcessor都被调用,执行接口的postProcessBeanFactory方法。
invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);

上面的代码中会从mdb中找出BeanFactoryPostProcessor接口的对象,并对它们进行排序,然后根据这些BeanFactoryPostProcessor依次对beanFactory处理。

spring源码:ApplicationContext的增强功能(li)的更多相关文章

  1. spring源码-bean之增强初始化-3

    一.ApplicationContext的中文意思是“应用上下文”,它继承自BeanFactory接口,除了包含BeanFactory的所有功能之外,在国际化支持.资源访问(如URL和文件).事件传播 ...

  2. spring源码:学习线索(li)

    一.spring xml配置(不包括AOP,主要了解在初始化及实例化过程中spring配置文件中每项内容的具体实现过程,从根本上掌握spring) <bean>的名字 &,alia ...

  3. spring源码深度解析-2功能扩展

    容器功能的扩展ApplicationContext用于扩展BeanFactory中现有的功能.究竟多出了哪些功能,进一步探索.写法上:BeanFactory bf = new XmlBeanFacto ...

  4. spring源码:Aware接口(li)

    一.spring容器中的aware接口介绍 Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAwa ...

  5. spring源码-开篇

    一.写博客也有一段时间了,感觉东西越来越多了,但是自己掌握的东西越来越少了,很多时候自己也在想.学那么多东西,到头来知道的东西越来越少了.是不是很奇怪,其实一点都不奇怪. 我最近发现了一个很大的问题, ...

  6. spring源码:web容器启动(li)

    web项目中可以集成spring的ApplicationContext进行bean的管理,这样使用起来bean更加便捷,能够利用到很多spring的特性.我们比较常用的web容器有jetty,tomc ...

  7. 创建ApplicationContext与BeanFactory时的区别-Spring源码学习之容器的基本实现

    传送门 可以加载XML两种方法 使用 BeanFactory 加载 XML BeanFactory bf = new XmlBeanFactory(new ClassPathResource(&quo ...

  8. Spring源码分析(二十二)功能扩展

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.增加SPEL语言的支持 二.增加属性注册编辑器 1. 使用自 ...

  9. Spring源码分析(十九)容器的功能扩展概览

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 经过前面几章的分析,相信大家已经对 Spring 中的容器功能有了简单 ...

  10. Spring源码阅读-ApplicationContext体系结构分析

    目录 继承层次图概览 ConfigurableApplicationContext分析 AbstractApplicationContext GenericApplicationContext Gen ...

随机推荐

  1. SharePoint2016安装的过程的”Microsoft.SharePoint.Upgrade.SPUpgradeException”错误解决方法

    前提 在windows server 2012的服务器上运行安装sharepoint2016出现如下错误: Could not load file or assembly ‘Microsoft.Dat ...

  2. ios 类似微信红点显示功能

    设计思路:给UIView增加一个分类 所有的视图都可以根据需要来进行红点显示 #import <UIKit/UIKit.h> @interface UIView (CHRRedDot) @ ...

  3. kvm 使用入门详解

    kvm 是虚拟化技术的一个典型实现,功能非常强大,使用很方便.kvm 本身主要实现对 CPU 的虚拟化,内存和IO的虚拟化使用了开源软件 qemu,qemu 是纯软件层面的虚拟化,其实就是个模拟器.k ...

  4. 《月之猎人 (Moon Hunters)》主角设计

    原文链接 游戏开发人员,你们好! 我是 Kitfox Games 工作室的总监 Tanya,我们的工作室位于加拿大的蒙特利尔,拥有六名员工. 我们 3 月份发布了<月之猎人>游戏的桌面版, ...

  5. JavaWeb的国际化

    国际化 1.国际化开发概述 1.1.软件的国际化 软件开发时,要使它能同时应对世界不同地区和国家的方法,并针对不同地区和国家的方法,提供相应的,符合来访者阅读习惯的页面或数据 国际化简称:i18n : ...

  6. D3.js学习(六)

    上节我们学习了如何绘制多条曲线, 以及给不同的曲线指定不同的坐标系.在这节当中,我们会对坐标轴标签相关的处理进行学习.首先,我们来想一个问题, 如何我们的x轴上的各个标签的距离比较近,但是标签名又比较 ...

  7. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. Enterprise Integration Pattern - 组成简介

    近些年来,越来越多的Web应用正在逐渐向大型化的方向发展.它们通常都会包含一系列相互协作的子服务.在开发过程中,如何让这些子服务协同工作常常是软件开发人员所最为头疼的问题,如各个子服务之间的数据表示不 ...

  9. 让ASP.NET接受有“潜在危险”的提交

    什么是有“潜在危险”的提交?马上动手写个简单的例子:   用Visual Studio创建一个空白的ASP.NET MVC程序,一切默认即可,添加一个空白的HomeController,增加一个Ind ...

  10. ASP.NET MVC Model元数据(四)

    ASP.NET MVC Model元数据(四) 前言 前面的篇幅讲解了Model元数据生成的过程,并没有对Model元数据生成过程的内部和Model元数据结构的详细解释.看完本篇后将会对Model元数 ...