spring源码:ApplicationContext的加强功能(li)

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

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

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事件并进行处理:app

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")); // 发布事件,监听器接收到事件消息
    }
}

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

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

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

其余细节点:spa

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

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

  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)的处理。xml

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处理。对象

相关文章
相关标签/搜索