Spring ApplicationContext事件机制:ApplicationEvent与ApplicationListener
ApplicationContext:这个接口功能有些强大,应该是spring框架的核心和基础。从它下面的接口声明就可以看出来。你会认为这个是spring的上下文,没错。但是我更偏向于它是一个具有丰富功能和主要地位的容器。public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory,Hie..
·
- 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缓存中查找)。
首先我们创建listener
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());
}
}
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>
测试:
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();
}
}
DemoRunner当中的一行代码:context.start(). 这个里面会发布一个ContextStartedEvent。里面包括applicationContext,从中我们可以获取所有注册的Bean。
更多推荐
已为社区贡献1条内容
所有评论(0)