Spring 中的事件监听的实现


这里我们不讨论事件监听的机制的原理,我们只讨论如何在项目中实现时间监听。
spring的事件监听是基于观察者模式。设计开发中。如下类与接口是我们必须要使用的。

ApplicationContext

首先我们了解一下ApplicationContext,还记得

  1. ApplicationContext ac=new ClassPathXmlApplicationContext("beans.xml");
  • 1
  • 1

ApplicationContext相当于Spring的一个与IOC容器连接的桥梁,通过getBean();方法,我们可以轻松的从IOC容器中获取Bean对象。
因为ApplicationContext是实现ApplicationEventPublisher的。查看ApplicationEventPublisher的源码,我们发现有一方法publishEvent。此方法便是发布事件的方法,即触发事件的方法,通过调用publishEvent方法,注入事件ApplicationEvent的子类,实现事件的触发。

  1. //这个是ApplicationContext类的声明
  2. public interface ApplicationContext extends EnvironmentCapable,ListableBeanFactory,HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver {//...}
  • 1
  • 2
  • 1
  • 2
  1. //ApplicationEventPublisher源码
  2. public interface ApplicationEventPublisher {
  3. //该类只有这一个方法,用于发布通知,需要事件作为参数
  4. void publishEvent(ApplicationEvent event);
  5. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

说了一大堆,就是想说ApplicationContext的

publicEvent(ApplicationEvent event);

方法是可以用来发布通知,相当于触发事件的事件源。

ApplicationContextAware

ApplicationContextAware类似于ServeletRequestAware,通过让Action实现Aware,使得Action初始化之后便可以获得一些资源,这里我们让Action实现ApplicationContext,使得Action拥有ApplicationContext,Action中拥有ApplicationContext之后就可以调用publicEvent方法进行通知

  1. public interface ApplicationContextAware extends Aware {
  2. void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
  3. }

ApplicationEvent

ApplicationEvent相当于一个事件,所有自定义事件都需要继承这个抽象类。在Eclipse中Ctrl+Shift+H调用类的层次结构列表,可以看到如下

Application下抽象子类ApplicationContextEvent的下面有4个已经实现好的事件
ContextClosedEvent(容器关闭时)
ContextRefreshedEvent(容器刷新是)
ContextStartedEvent(容器启动时候)
ContextStoppedEvent(容器停止的时候)
同样,这四个事件都继承了ApplicationEvent,如果我们想自定义事件,也可以通过继承ApplicationEvent来实现
嗯,同样是一句话总结ApplicationEvent就是一个抽象类,创建时间的时候只需要继承它就可以。

ApplicationListener

从名字可以看出来,这是一个监听器。为什么需要监听器呢?监听器是用于接收事件,并触发事件的操作,这样说起来可能有点费解,简单的说就是,Listener是监听ApplicationContext.publishEvent,方法的调用,一旦调用publishEvent,就会执行ApplicaitonListener中的方法,下面这个是ApplicationContext的源码。

  1. public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
  2. /**
  3. * publishEvent触发该方方法
  4. * 可以在该方法中写各种业务逻辑
  5. */
  6. void onApplicationEvent(E event);
  7. }

这里是实际代码实现的过程

  1. 新建一个MyEvent的类,继承ApplicationEvent抽象类
  1. package cn.blueboz.elec.event;
  2. import org.springframework.context.ApplicationEvent;
  3. public class MyEvent extends ApplicationEvent {
  4. //存放构造器送入的值
  5. private String msg;
  6. //构造器参数可以随意设置,这里为了方便调试,设置为字符串
  7. public MyEvent(String msg) {
  8. super(msg);
  9. this.msg=msg;
  10. }
  11. //自定义一个方法,这个方法也可以随意写,这里也是测试用
  12. public void myevent(){
  13. System.out.println("********My event**************");
  14. System.out.println(msg);
  15. System.out.println("*******************************");
  16. }
  17. }

2.新建一个监听器MyListener

  1. package cn.blueboz.elec.listener;
  2. import org.springframework.context.ApplicationEvent;
  3. import org.springframework.context.ApplicationListener;
  4. import org.springframework.context.event.ContextClosedEvent;
  5. import org.springframework.context.event.ContextRefreshedEvent;
  6. import org.springframework.context.event.ContextStartedEvent;
  7. import org.springframework.context.event.ContextStoppedEvent;
  8. import org.springframework.stereotype.Service;
  9. import cn.blueboz.elec.event.HisEvent;
  10. import cn.blueboz.elec.event.MyEvent;
  11. //注入IOC容器中
  12. @Service("myListener")
  13. public class MyListener implements ApplicationListener<ApplicationEvent> {
  14. //调用ApplicationContext.publishEvent方法时会触发执行该方法
  15. @Override
  16. public void onApplicationEvent(ApplicationEvent event) {
  17. //判断事件为MyEvent时候执行
  18. if(event instanceof MyEvent){
  19. //强制转换
  20. MyEvent evt=(MyEvent) event;
  21. //执行自定义事件中的自定义方法
  22. evt.myevent();
  23. }
  24. //如果容器关闭时,触发
  25. if(event instanceof ContextClosedEvent){
  26. ContextClosedEvent cce=(ContextClosedEvent) event;
  27. System.out.println("#####################");
  28. System.out.println("容器关闭");
  29. System.out.println(cce);
  30. System.out.println("#####################");
  31. }
  32. //容器刷新时候触发
  33. if(event instanceof ContextRefreshedEvent){
  34. ContextRefreshedEvent cre=(ContextRefreshedEvent) event;
  35. System.out.println("#####################");
  36. System.out.println("容器刷新");
  37. System.out.println(cre);
  38. System.out.println("#####################");
  39. }
  40. //容器启动的时候触发
  41. if(event instanceof ContextStartedEvent){
  42. ContextStartedEvent cse=(ContextStartedEvent) event;
  43. System.out.println("#####################");
  44. System.out.println("容器启动");
  45. System.out.println(cse);
  46. System.out.println("#####################");
  47. }
  48. //容器停止时候触发
  49. if(event instanceof ContextStoppedEvent){
  50. ContextStoppedEvent cse=(ContextStoppedEvent) event;
  51. System.out.println("#####################");
  52. System.out.println("容器停止");
  53. System.out.println(cse);
  54. System.out.println("#####################");
  55. }
  56. }
  57. }

3.最后,我们要再Action中发布通知publishEvent;

  1. package cn.blueboz.elec.web.action;
  2. import javax.annotation.Resource;
  3. import org.apache.struts2.interceptor.ServletRequestAware;
  4. import org.springframework.beans.BeansException;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.ApplicationContextAware;
  7. import org.springframework.context.annotation.Scope;
  8. import org.springframework.context.support.ClassPathXmlApplicationContext;
  9. import org.springframework.stereotype.Controller;
  10. import cn.blueboz.elec.domain.ElecText;
  11. import cn.blueboz.elec.event.MyEvent;
  12. import cn.blueboz.elec.service.IElecTextService;
  13. //指定为prototype原型,对应每一个请求都会产生一个实例对象
  14. @Controller("elecTextAction")
  15. @Scope(value="prototype")
  16. public class ElecTextAction extends BaseAction<ElecText> implements ApplicationContextAware,ServletRequestAware {
  17. //首先获得模型驱动对象
  18. ElecText elecText=getModel();
  19. protected ApplicationContext applicationContext;
  20. //注入Service指定从Spring的IOC容器中注入的对象的名称
  21. @Resource(name=IElecTextService.SERVICE_NAME)
  22. private IElecTextService elecTextService;
  23. public String save(){
  24. //从表单中传送过来的实例对象
  25. elecTextService.saveElecText(elecText);
  26. /**
  27. * 请关注这一行代码,在页面中访问时候调用save方法
  28. * save方法中执行了publishEvent方法发布通知。
  29. * 传入参数是自定义事件MyEvent
  30. */
  31. applicationContext.publishEvent(new MyEvent("在Action中的save方法Public了Event"));
  32. return "save";
  33. }
  34. @Override
  35. public void setApplicationContext(ApplicationContext applicationContext)
  36. throws BeansException {
  37. this.applicationContext=applicationContext;
  38. }
  39. }

4.启动Tomcat时候命令行输出

  1. #####################
  2. 容器刷新
  3. org.springframework.context.event.ContextRefreshedEvent[source=Root WebApplicationContext: startup date [Fri Nov 20 17:12:47 CST 2015]; root of context hierarchy]
  4. #####################

访问页面的时候,命令行输出,可以看出,触发了MyEvent方法输出。

  1. ********My event**************
  2. Action中的save方法PublicEvent

Spring 监听的更多相关文章

  1. spring监听机制——观察者模式的应用

    使用方法 spring监听模式需要三个组件: 1. 事件,需要继承ApplicationEvent,即观察者模式中的"主题",可以看做一个普通的bean类,用于保存在事件监听器的业 ...

  2. spring监听与IBM MQ JMS整合

    spring xml 的配置: 文件名:applicationContext-biz-mq.xml <?xml version="1.0" encoding="UT ...

  3. Spring监听,ApplicationListener

    import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; import ...

  4. 监听spring加载完成后事件

    有这个想法是在很早以前了,那时的我没有接触什么缓存技术,只知道hibernate有个二级缓存.没有用过memcache,也没有使用过redis. 只懂得将数据放到数组里或者集合里,一直不去销毁它(只有 ...

  5. Spring Boot实现一个监听用户请求的拦截器

    项目中需要监听用户具体的请求操作,便通过一个拦截器来监听,并继续相应的日志记录 项目构建与Spring Boot,Spring Boot实现一个拦截器很容易. Spring Boot的核心启动类继承W ...

  6. Spring DM所提供的Bundle监听接口OsgiBundleApplicationContextListener

    通过使用Spring DM提供的监听接口,我们可以更好的对服务进行管控,其实该接口也非常简单就能使用上,只要自定义一个类实现OsgiBundleApplicationContextListener接口 ...

  7. JavaEE开发之Spring中的事件发送与监听以及使用@Profile进行环境切换

    本篇博客我们就来聊一下Spring框架中的观察者模式的应用,即事件的发送与监听机制.之前我们已经剖析过观察者模式的具体实现,以及使用Swift3.0自定义过通知机制.所以本篇博客对于事件发送与监听的底 ...

  8. 【Spring】关于SpringMvc监听的知识点

    一,在使用Spring系列框架时,我们需要在Web.xml配置Spring的监听:ContextLoaderListener ContextLoaderListener的作用就是,在Web容器初始化时 ...

  9. Spring知识点回顾(07)事件发布和监听

    Spring知识点回顾(07)事件发布和监听 1.DemoEvent extends ApplicationEvent { public DemoEvent(Object source, String ...

随机推荐

  1. js 高效拼接字符串

    <script>//如果我们大量使用+=进行字符串拼接的话,将会使界面失去响应(卡死状态) //高效拼接字符串 var StringBuilder=function() { this.da ...

  2. thread == 售票

    import org.apache.xerces.util.SymbolTable; public class ThreadDemo1 { public static void main(String ...

  3. python 稀疏向量和矩阵的表示形式

    http://blog.csdn.net/nkwangjie/article/details/17502443 http://blog.csdn.net/bitcarmanlee/article/de ...

  4. create-react-app之proxy

    [create-react-app之proxy] create-react-app可以用于一键创建web_client环境,默认使用webpack-dev-server.但在开发过程中,往往需要cli ...

  5. python网络编程之C/S架构介绍

    标签(空格分隔): c/s架构介绍 什么是C/S架构 C指的是client(客户端软件),S指的是Server(服务端软件),后续我们可以试着写个c/s软件实现服务器软件与客户端软件基于网络通信: 计 ...

  6. burpsuite的使用(三)

    send to repeater 手动提交,注入. 将post请求改成get请求 直接就可以看到页面 生成csrf POC代码 点击在浏览器中测试,copy 拿到浏览器里访问 或者拷贝出来 保存到文本 ...

  7. Linux系统缓冲区溢出

    Linux系统下穿越火线-缓冲区溢出 原理:crossfire 1.9.0 版本接受入站 socket 连接时存在缓冲区溢出漏洞. 工具: 调试工具:edb: ###python在漏洞溢出方面的渗透测 ...

  8. VM虚拟机的配置文件(.vmx)损坏

    为了禁用时间同步,使用sublime修改vmx文件 文件第一行为.encoding = "GBK" 修改完毕,无法打开虚拟机,报 VM虚拟机的配置文件(.vmx)损坏错误 因为su ...

  9. 百度浏览器 UserAgent

    Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 BIDUBrowser ...

  10. ActiveMQ之java Api

    ActiveMQ 安全机制 activemq的web管理界面:http://127.0.0.1:8161/admin activemq管控台使用jetty部署,所以需要修改密码则需要修改相应的配置文件 ...