Spring ApplicationContext事件机制:ApplicationEvent与ApplicationListener
来源:互联网 发布:扫码查价软件 编辑:程序博客网 时间:2024/05/29 04:22
最近看一个项目的demo的时候,无意间看到了一个listener,跟进去看了下,对spring的事件机制有了个大致的了解。先看看几个概念:
- ApplicationContext:这个接口功能有些强大,应该是spring框架的核心和基础。从它下面的接口声明就可以看出来。你会认为这个是spring的上下文,没错。但是我更偏向于它是一个具有丰富功能和主要地位的容器。
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver
- ApplicationEvent:这是抽象类, java.util.EventObject的子类,里面有一个timestamp的属性用于记录事件发生的时间和一个source对象纪录event source。 我的理解是它是一个事件, 但是更是一个事件信息/数据的载体。Srping 内置几个实现:ContextClosedEvent, ContextStartedEvent,ContextRefreshedEvent,ContextStoppedEvent。这几个事件实例包含的数据就是ApplicationContext对象。
- ApplicationListener:顾名思义,这个是个listener,spring的事件机制是基于观察者设计模式的。里面有个onApplicationEvent方法,用于对事件的处理。
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event);}
这三者是什么关系,应该很显然了。ApplicationContext 通过publishEvent方法(该方法继承于接口ApplicationEventPublisher)发布事件(ApplicaitonEvent), 然后由ApplicationListener监听处理。
具体是怎么协作的呢?来看一个spring的实现:
ApplicationContext的实现类ClassPathXmlApplicationContext的publishEvent方法。
public void publishEvent(ApplicationEvent event) {....... getApplicationEventMulticaster().multicastEvent(event); if (this.parent != null) { this.parent.publishEvent(event); }}
public void multicastEvent(final ApplicationEvent event) { for (final ApplicationListener listener : getApplicationListeners(event)) { Executor executor = getTaskExecutor(); if (executor != null) { executor.execute(new Runnable() { @Override public void run() { listener.onApplicationEvent(event); } }); } else { listener.onApplicationEvent(event); } } }
其中multicastEvent方法会根据注册进来的事件的类型,找到对应的监听者listener,(其实就是根据class type的一个map缓存中查找)。有兴趣的同学可以参考实现AbstractApplicationEventMulticaster。 那么你会问,这个map啥
时候构建的?啥时候注册时间进去的?当然是spring 加载你的配置的时候啊。你得注册!!! 还是看下面的demo 吧。˜讲了这么多了,应该来看个demo啦… …
首先我们创建listener
/** * @author mian.hem * */public class DemoApplicationListener implements ApplicationListener<DemoApplicationEvent> { @Override public void onApplicationEvent(DemoApplicationEvent event) { System.out.println("on application event"); System.out.println("the event object is :" + event); System.out.println("the event name is :" + event.getEventName()); }}
/** * @author mian.hem * */public class ContextStartedListener implements ApplicationListener<ContextStartedEvent> { @Override public void onApplicationEvent(ContextStartedEvent event) { DemoApplicationListener listener = event.getApplicationContext().getBean("listener", DemoApplicationListener.class); if (listener != null) { System.out.println("listener got."); } else { System.out.println("listener absent, please check!"); } }}
然后就是对应的event,很简单,当中包括一个属性eventName。
public class DemoApplicationEvent extends ApplicationEvent { private String eventName; public String getEventName() { return eventName; } public void setEventName(String eventName) { this.eventName = eventName; } public DemoApplicationEvent(Object source) { super(source); } /** * */ private static final long serialVersionUID = -3452985719192365159L;}
再者, 就是对应的spring配置:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <bean id="listener" name="listener" class="com.maywe.spring.applicationlistener.DemoApplicationListener"> </bean> <bean id="ctxStartedlistener" name="ctxStartedlistener" class="com.maywe.spring.applicationlistener.ContextStartedListener"> </bean></beans>
最后, 就是我们的DemoRunner
public class DemoRunner { /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( "classpath*:/context/spring-context-application-listener.xml"); context.start(); String targetObj = "i am the target object"; DemoApplicationEvent event = new DemoApplicationEvent(targetObj); event.setEventName("event name"); context.publishEvent(event); Thread.sleep(3000); context.close(); }}
一起来看看结果吧 --->
listener got.on application eventthe event object is :com.maywe.spring.applicationlistener.DemoApplicationEvent[source=i am the target object]the event name is :event name
注意:DemoRunner当中的一行代码:context.start(). 这个里面会发布一个ContextStartedEvent。里面包括applicationContext,从中我们可以获取所有注册的Bean。
- Spring ApplicationContext事件机制:ApplicationEvent与ApplicationListener
- Spring中使用ApplicationContext进行事件的监听之ApplicationEvent,ApplicationListener
- Spring 通过ApplicationListener&ApplicationEvent实现事件监听
- Spring ApplicationEvent和ApplicationListener
- spring---ApplicationListener,ApplicationEvent
- spring---ApplicationListener,ApplicationEvent
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring的监听事件ApplicationListener和ApplicationEvent及@EventListener用法
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring 的 ApplicationEvent and ApplicationListener
- Spring 的 ApplicationEvent ,ApplicationListener,ApplicationContextAware
- Spring 的 ApplicationEvent and ApplicationListener
- Spring 的 ApplicationEvent和ApplicationListener
- Spring 的 ApplicationEvent and ApplicationListener
- python递归目录子目录列出目录和文件
- SQL学习网站
- python numpy的学习
- 大话设计模式-第12章 牛市股票还会亏钱?--外观模式
- Ehcache配置详解及CacheManager使用
- Spring ApplicationContext事件机制:ApplicationEvent与ApplicationListener
- 多重继承
- HDU 1241 Oil Deposits
- Supervisor的安装与使用入门
- ant常用task之condition
- 开放平台中的鉴权的实现
- HTML5 MathMl
- 非暴力沟通
- Python中的模块