ApplicationContext
事件机制是观察者设计模式的实现,通过ApplicationEvent
类和ApplicationListener
接口,可以实现ApplicationContext
事件处理。如果容器中有一个ApplicationListener Bean
,每当ApplicationContext
发布ApplicationEvent
时,ApplicationListener Bean
将自动被触发。Spring的事件框架有如下两个重要的成员:
1. ApplicationEvent:容器事件,必须由ApplicationContext发布
2. ApplicationListener:监听器,可由容器中的任何监听器Bean担任
提示 :观察者模式和委托事件模型的介绍和例子请点这里
实际上,Spring的事件机制与所有时间机制都基本相似,它们都由事件源、事件和事件监听器组成。只是此处的事件源是ApplicationContext
,且事件必须由Java程序显式触发。
//程序先定义了一个ApplicationEvent类 继承自ApplicationEvent
public class EmailEvent extends ApplicationEvent {
private String address;
private String text;
public EmailEvent(Object source, String address, String text) {
super(source);
this.address = address;
this.text = text;
}
public EmailEvent(Object source) {
super(source);
}
// getter and setter ...
}
只要一个类继承了
ApplicationEvent
基类,则这个对象就可以作为spring容器的事件。容器事件的监听器类必须实现
ApplicationListener
接口,实现onApplicationEvent(ApplicationEvent event)
方法,每当容器发生任何事件时,此方法都会被触发。
public class EmailNotifier implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof EmailEvent) {
EmailEvent emailEvent = (EmailEvent) event;
System.out.println("邮件地址:" + emailEvent.getAddress());
System.out.println("邮件内容:" + emailEvent.getText());
} else {
System.out.println("其他事件:" + event);
}
}
}
注意:spring4.2之后支持使用
@EventListener
注解来标识监听方法。可以不实现现ApplicationListener
.
public class EmailNotifier {
@EventListener
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof EmailEvent) {
EmailEvent emailEvent = (EmailEvent) event;
System.out.println("邮件地址:" + emailEvent.getAddress());
System.out.println("邮件内容:" + emailEvent.getText());
} else {
System.out.println("其他事件:" + event);
}
}
}
将监听器配置在容器中,spring容器会把这个bean当成 容器事件的监听器。
<bean class="com.erick.d1.hello.EmailNotifier"/>
当系统创建spring容器,加载spring容器时会自动出发一些容器事件,容器事件监听器可以监听到这些事件。
程序也可以调用ApplicationContext
的publishEvent()
方法来主动出发容器事件。
//创建ApplicationEvent对象
EmailEvent event = new EmailEvent("test", "123@123.com", "this is test");
//发布容器事件
ctx.publishEvent(event);
注意:如果Bean想发布事件,则Bean必须获得其容器的引用。如果程序中没有直接获取容器的引用,则应该让Bean实现ApplicationContextAware或者BeanFactoryAware接口,从而可以获得容器的引用。
Spring提供如下几个内置事件:
ContextRefreshedEvent:
ApplicationContext
容器初始化或刷新时触发该事件。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext
容器已就绪可用ContextStartedEvent:当使用
ConfigurableApplicationContext
(ApplicationContext
的子接口)接口的start()
方法启动ApplicationContext
容器时触发该事件。容器管理生命周期的Bean实例将获得一个指定的启动信号,这在经常需要停止后重新启动的场合比较常见ContextClosedEvent:当使用
ConfigurableApplicationContext
接口的close()
方法关闭ApplicationContext
时触发该事件ContextStoppedEvent:当使用
ConfigurableApplicationContext
接口的stop()
方法使ApplicationContext
容器停止时触发该事件。此处的停止,意味着容器管理生命周期的Bean实例将获得一个指定的停止信号,被停止的Spring容器可再次调用start()
方法重新启动RequestHandledEvent:Web相关事件,只能应用于使用
DispatcherServlet
的Web应用。在使用Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。RequestHandledEvent:Web相关事件,只能用于
DispatcherServlet
的web应用中。在使用Spring作为前端MVC控制器时,当Spring处理请求结束后,系统会自动触发该事件。
Spring 4.0.3之后spring还增加了
SessionConnectedEvent
SessionConnectEvent
SessioonDisconnectEvent
这三个事件,他们都用于为Spring新增的WebSocket功能服务。