【十五】Spring Boot 之 事件监听(自定义ApplicationEvent、ApplicationListener)(实现ApplicationContextAware接口)
一、简介:ApplicationContext事件机制是观察者设计模式的实现。Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。Spring中有一些内置的事件如下容器事件(ApplicationContextEvent):ContextRefresh...
一、简介:
ApplicationContext事件机制是观察者设计模式的实现。
Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
Spring中有一些内置的事件如下
容器事件(ApplicationContextEvent):
ContextRefresheEvent:
ApplicationContext容器初始化或刷新时触发该事件。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用
ContextStartedEvent:
当spring启动时,或者说是context调用start()方法时,会触发此事件
ContextStoppedEvent:
当spring停止时,或者说context调用stop()方法时,会触发此事件
ContextClosedEvent:
当spring关闭时,或者说context调用close()方法时,会触发此事件
Web应用相关(RequestHandledEvent):
ServletRequestHandledEvent:
每次请求处理结束后,容器上下文都发布了一个ServletRequestHandledEvent事件
二、自定义事件和事件监听器
步骤
1.自定义事件:扩展ApplicationEvent类,需要有构造函数。
2.自定义事件监听器:实现ApplicationListener接口,重写onApplicationEvent方法,该方法处理监听到某个时间后做哪些操作。
3.通过ApplicationContext发布事件
代码演示
自定义事件
msg为发布事件时需要给监听器传递的参数
package com.sid.util.event;
import org.springframework.context.ApplicationEvent;
/**
* @program: springboot
* @description: 自定义容器事件类
* @author: Sid
* @date: 2018-11-21 10:42
* @since: 1.0
**/
public class MyApplicationEvent extends ApplicationEvent {
private String msg;
public MyApplicationEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public MyApplicationEvent(Object source) {
super(source);
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
自定义事件监听器
onApplicationEvent()方法入参介绍
如果入参是ApplicationEvent,则每当容器内发生任何事件时,此方法都会被触发
如果入参是MyApplicationEvent,则只有容器内发生MyApplicationEvent事件时,此方法才会被触发
package com.sid.util.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
/**
* @program: springboot
* @description: 自定义事件监听器 第一种方式 实现ApplicationListener接口
* @author: Sid
* @date: 2018-11-21 10:43
* @since: 1.0
**/
@Component
public class MyApplicationListener implements ApplicationListener {
@Override
//参数的范围越广泛,监听到的事件越多
//如果入参是ApplicationEvent,则每当容器内发生任何事件时,此方法都会被触发
//如果入参是MyApplicationEvent,则只有容器内发生如果入参是MyApplicationEvent事件时,此方法才会被触发
//之前做的某个功能,起了很多线程,就是因为入参范围太广泛了,触发了很多次
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(event.getClass().getName() + "被监听......");
if(event instanceof MyApplicationEvent){
MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
System.out.println("MyApplicationEvent.msg is :"+(myApplicationEvent.getMsg()));
}
}
}
/**
* @program: springboot
* @description: 自定义事件监听器 第二种方式
* 写一个带参的方法,参数为需要监听的事件的父类或需要监听的事件
* 使用@EventListener
* @author: Sid
* @date: 2018-11-21 10:43
* @since: 1.0
*
@Component
public class MyApplicationListener {
//参数的范围越广泛,监听到的事件越多
//如果入参是ApplicationEvent,则每当容器内发生任何事件时,此方法都会被触发
//如果入参是MyApplicationEvent,则只有容器内发生如果入参是MyApplicationEvent事件时,此方法才会被触发
//之前做的“排队导出”,同事换了包过后,起了很多线程,就是因为入参范围太广泛了,触发了很多次
@EventListener
public void onApplicationEvent(ApplicationEvent event) {
System.out.println(event.getClass().getName() + "被监听......");
if(event instanceof MyApplicationEvent){
MyApplicationEvent myApplicationEvent = (MyApplicationEvent) event;
System.out.println("MyApplicationEvent.msg is :"+(myApplicationEvent.getMsg()));
}
}
}*/
这里为了在普通类中得到ApplicationContext而不重新加载一次容器,实现了ApplicationContextAware接口
package com.sid.util.event;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @program: springboot
* @description:
* @author: Sid
* @date: 2018-11-21 11:33
* @since: 1.0
**/
@Component
public class SpringBootBeanUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringBootBeanUtil.applicationContext == null) {
SpringBootBeanUtil.applicationContext = applicationContext;
}
System.out.println("========ApplicationContext配置成功========");
System.out.println("========在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象========");
System.out.println("========applicationContext="+ SpringBootBeanUtil.applicationContext +"========");
}
/**
* 获取applicationContext
* @return
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 通过name获取 Bean.
* @param name
* @return
*/
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/**
* 通过class获取Bean.
* @param clazz
* @return
*/
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/**
* 通过name,以及Clazz返回指定的Bean
* @param name
* @param clazz
* @return
*/
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
}
发布事件
package com.sid.controller;
import com.sid.util.event.MyApplicationEvent;
import com.sid.util.event.SpringBootBeanUtil;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @program: springboot
* @description:
* @author: Sid
* @date: 2018-11-21 10:59
* @since: 1.0
**/
@Controller
public class EventController {
@ResponseBody
@RequestMapping(value = "/myApplicationEvent")
public String testEvent()
{
ApplicationContext context = SpringBootBeanUtil.getApplicationContext();
//发布事件
context.publishEvent(new MyApplicationEvent(new Object(),"sid"));
return "test EventController testEvent ";
}
}
测试结果
org.springframework.context.event.ContextRefreshedEvent被监听......
2018-11-21 12:23:05.082 INFO [main]org.apache.coyote.http11.Http11NioProtocol.log:179 -Initializing ProtocolHandler ["http-nio-8088"]
2018-11-21 12:23:05.082 INFO [main]org.apache.coyote.http11.Http11NioProtocol.log:179 -Starting ProtocolHandler ["http-nio-8088"]
2018-11-21 12:23:05.083 INFO [main]org.apache.tomcat.util.net.NioSelectorPool.log:179 -Using a shared selector for servlet write/read
2018-11-21 12:23:05.086 INFO [main]org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainer.start:201 -Tomcat started on port(s): 8088 (http)
org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent被监听......
org.springframework.boot.context.event.ApplicationReadyEvent被监听......com.sid.util.event.MyApplicationEvent被监听......
MyApplicationEvent.msg is :sid
更多推荐
所有评论(0)