文章目录
Spring中的事件处理
Spring 的核心是 ApplicationContext ,它负责管理 beans 的完整生命周期。当加载 beans 时,ApplicationContext 发布某些类型的事件。例如,当上下文启动时,ContextStartedEvent 发布,当上下文停止ContextStoppedEvent发布。
通过 ApplicationEvent 类和 ApplicationListener 接口来提供在 ApplicationContext 中处理事件。如果一个 bean 实现 ApplicationListener ,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知。
Spring 提供了以下的标准事件:
序号
Spring 内置事件 & 描述
1
ContextRefreshedEvent* ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext*接口中使用 refresh() 方法来发生。
2
ContextStartedEvent 当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。
3
ContextStoppedEvent 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。
4
ContextClosedEvent 当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。
5
RequestHandledEvent 这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。
由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
监听上下文事件
为了监听上下文事件,一个 bean 应该实现只有一个方法 onApplicationEvent() 的 ApplicationListener 接口。因此,我们写一个例子来看看事件是如何传播的,以及如何可以用代码来执行基于某些事件所需的任务。
让我们在恰当的位置使用 Eclipse IDE,然后按照下面的步骤来创建一个 Spring 应用程序:
步骤
描述
1
创建一个名称为 SpringEvent Test 的项目,并且在创建项目的 src 文件夹中创建一个包com.szxy
2
使用 Add External JARs 选项,添加所需的 Spring 库
3
在 com.szxy包中创建 Java 类 HelloSpringEvent、 CStartEventHandler、 CStopEventHandler* 和 Start
4
在 src 文件夹中创建 Bean 的配置文件 applicationContext.xml.xml
5
最后一步是创建的所有 Java 文件和 Bean 配置文件的内容,并运行应用程序,解释如下所示.
这里是 HelloSpringEvent.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
package com.szxy; public class HelloSpringEvent { private String msg; public HelloSpringEvent(){ System.out.println("HelloSpringEvent 初始化"); } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } }
下面是 CStartEventHandler.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
package com.szxy; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextStartedEvent; /** * ContextStartedEvent: * 当使用 ConfigurableApplicationContext 接口中的 start()方法启动 ApplicationContext时, * 该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。 * @author Administrator * */ public class CStartEventHandler implements ApplicationListener<ContextStartedEvent>{ @Override public void onApplicationEvent(ContextStartedEvent event) { System.out.println("ContextStartedEvent start!!"); } }
下面是 CStopEventHandler.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
package com.szxy; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextStoppedEvent; /** * ContextStoppedEvent:
大专栏 Spring中的事件处理 span> * 当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时, * 发布这个事件。你可以在接受到这个事件后做必要的清理的工作。 * @author Administrator * */ public class CStopEventHandler implements ApplicationListener<ContextStoppedEvent>{ @Override public void onApplicationEvent(ContextStoppedEvent event) { System.out.println("ContextStoppedEvent stop!!"); } }
下面是 Start.java 文件的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
package com.szxy; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Start { public static void main(String[] args) { //加载spring配置文件,初始化所有的bean ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); //启动spring容器 ac.start(); HelloSpringEvent hello = ac.getBean("helloSpringEvent", HelloSpringEvent.class); System.out.println(hello.getMsg()); //停止spring容器 ac.stop(); } }
下面是配置文件 applicationContext.xml 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="helloSpringEvent" class="com.szxy.HelloSpringEvent"> <property name="msg"> <value>Test SpringEvent!!</value> </property> </bean> <bean id="cStartEventHandler" class="com.szxy.CStartEventHandler"></bean> <bean id="cStopEventHandler" class="com.szxy.CStopEventHandler"></bean> </beans>
一旦你完成了创建源和 bean 的配置文件,我们就可以运行该应用程序。如果你的应用程序一切都正常,将输出以下消息:
1 2 3 4
HelloSpringEvent 初始化 ContextStartedEvent start!! Test SpringEvent!! ContextStoppedEvent stop!!
注意:
由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
例如:
CStartEventHandler类的监听函数处理中加入一个阻塞调用System.in.read();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
package com.szxy; import java.io.IOException; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextStartedEvent; /** * ContextStartedEvent: * 当使用 ConfigurableApplicationContext 接口中的 start()方法启动 ApplicationContext时, * 该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。 * @author Administrator * */ public class CStartEventHandler implements ApplicationListener<ContextStartedEvent>{ @Override public void onApplicationEvent(ContextStartedEvent event) { System.out.println("ContextStartedEvent start!!"); try { System.in.read(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
运行结果:
1 2
HelloSpringEvent 初始化 ContextStartedEvent start!!
可以看出进程被阻塞了,程序不会往下继续执行
参考:
https://wiki.jikexueyuan.com/project/spring/event-handling-in-spring.html