Spring 监听

Spring 中的事件监听的实现



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

ApplicationContext

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

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

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

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

}
  • 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方法进行通知

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

ApplicationEvent

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

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

ApplicationListener

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

public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

    /**
     * publishEvent触发该方方法
     * 可以在该方法中写各种业务逻辑
     */
    void onApplicationEvent(E event);

}

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

  1. 新建一个MyEvent的类,继承ApplicationEvent抽象类
package cn.blueboz.elec.event;

import org.springframework.context.ApplicationEvent;

public class MyEvent extends ApplicationEvent {
    //存放构造器送入的值
    private String msg;
    //构造器参数可以随意设置,这里为了方便调试,设置为字符串
    public MyEvent(String msg) {
        super(msg);
        this.msg=msg;
    }
    //自定义一个方法,这个方法也可以随意写,这里也是测试用
    public void myevent(){
        System.out.println("********My event**************");
        System.out.println(msg);
        System.out.println("*******************************");
    }
}


2.新建一个监听器MyListener

package cn.blueboz.elec.listener;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.stereotype.Service;

import cn.blueboz.elec.event.HisEvent;
import cn.blueboz.elec.event.MyEvent;

//注入IOC容器中
@Service("myListener")
public class MyListener implements ApplicationListener<ApplicationEvent> {
    //调用ApplicationContext.publishEvent方法时会触发执行该方法
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        //判断事件为MyEvent时候执行
        if(event instanceof MyEvent){
            //强制转换
            MyEvent evt=(MyEvent) event;
            //执行自定义事件中的自定义方法
            evt.myevent();
        }
        //如果容器关闭时,触发
        if(event instanceof ContextClosedEvent){
            ContextClosedEvent cce=(ContextClosedEvent) event;
            System.out.println("#####################");
            System.out.println("容器关闭");
            System.out.println(cce);
            System.out.println("#####################");
        }
        //容器刷新时候触发
        if(event instanceof ContextRefreshedEvent){
            ContextRefreshedEvent cre=(ContextRefreshedEvent) event;
            System.out.println("#####################");
            System.out.println("容器刷新");
            System.out.println(cre);
            System.out.println("#####################");
        }
        //容器启动的时候触发
        if(event instanceof ContextStartedEvent){
            ContextStartedEvent cse=(ContextStartedEvent) event;
            System.out.println("#####################");
            System.out.println("容器启动");
            System.out.println(cse);
            System.out.println("#####################");
        }
        //容器停止时候触发
        if(event instanceof ContextStoppedEvent){
            ContextStoppedEvent cse=(ContextStoppedEvent) event;
            System.out.println("#####################");
            System.out.println("容器停止");
            System.out.println(cse);
            System.out.println("#####################");
        }
    }

}

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

package cn.blueboz.elec.web.action;

import javax.annotation.Resource;

import org.apache.struts2.interceptor.ServletRequestAware;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;

import cn.blueboz.elec.domain.ElecText;
import cn.blueboz.elec.event.MyEvent;
import cn.blueboz.elec.service.IElecTextService;

//指定为prototype原型,对应每一个请求都会产生一个实例对象
@Controller("elecTextAction")
@Scope(value="prototype")
public class ElecTextAction extends BaseAction<ElecText> implements ApplicationContextAware,ServletRequestAware {
    //首先获得模型驱动对象

    ElecText elecText=getModel();
    protected ApplicationContext applicationContext;
    //注入Service指定从Spring的IOC容器中注入的对象的名称
    @Resource(name=IElecTextService.SERVICE_NAME)
    private IElecTextService elecTextService;

    public String save(){
        //从表单中传送过来的实例对象
        elecTextService.saveElecText(elecText);
        /**
         * 请关注这一行代码,在页面中访问时候调用save方法
         * save方法中执行了publishEvent方法发布通知。
         * 传入参数是自定义事件MyEvent
         */
        applicationContext.publishEvent(new MyEvent("在Action中的save方法Public了Event"));
        return "save";
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext=applicationContext;
    }
}

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

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

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

********My event**************
在Action中的save方法Public了Event
时间: 2024-11-08 12:22:24

Spring 监听的相关文章

spring监听与IBM MQ JMS整合

spring xml 的配置: 文件名:applicationContext-biz-mq.xml [html] view plain copy print? <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001

Spring 监听session 失效方法

public class SessionCounter implements HttpSessionListener { private static int activeSessions =0;   /* Session创建事件 */   public void sessionCreated(HttpSessionEvent event) { //创建session }   /* Session失效事件 */   public void  sessionDestroyed(HttpSessio

Spring监听,ApplicationListener

import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.beans.factory.annotation.Qualifier; i

Spring架构揭秘-事件监听机制

一.事件监听机制概述 二.事件监听机制结构 三.Spring监听机制架构 Spring的Application拥有发布事件并且注册事件监听器的能力,拥有一套完整的事件发布和监听机制.在Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器,在众多的框架和组件中,建立一套事件机制通常是基于这两个接口来进行扩展. 在一个事件体系中,有以下几个重要的概念. 1.事件源:事件对象的产生者,任何一个EventObject

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

通过使用Spring DM提供的监听接口,我们可以更好的对服务进行管控,其实该接口也非常简单就能使用上,只要自定义一个类实现OsgiBundleApplicationContextListener接口,实现onOsgiApplicationEvent方法,并将自定义类注册成OSGI服务,通过判断event的事件类型来执行相应逻辑处理,同时也可以获取到当前监听的Bundle,从而达到更深层次的监控, public class ListenerDemo implements OsgiBundleAp

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

一,在使用Spring系列框架时,我们需要在Web.xml配置Spring的监听:ContextLoaderListener ContextLoaderListener的作用就是,在Web容器初始化时自动加载所对应的applicationContext.xml等配置文件,以帮助Spring完成其他初始化操作 语法是 这样在默认情况下,当Web容器启动时,系统会自动从web-INF文件夹下寻找一个叫applicationContext.xml的文件,并加载它进行初始化操作! 但是我们同样可以修改a

rabbitMq与spring boot搭配实现监听

在我前面有一篇博客说到了rabbitMq实现与zk类似的watch功能,但是那一篇博客没有代码实例,后面自己补了一个demo,便于理解.demo中主要利用spring boot的配置方式, 一.消费者(也就是watcher)配置 配置都采用spring的注解进行配置 1.创建连接 @Bean public ConnectionFactory createConnectionFactory() { CachingConnectionFactory connectionFactory = new C

spring boot 源码赏析之事件监听

使用spring Boot已经快1年多了,期间一直想点开springboot源码查看,但由于种种原因一直未能如愿(主要是人类的惰性...),今天就拿springboot 的监听事件祭刀. springboot 中常用的事件监听主要有ApplicationStartedEvent,ApplicationEnviromentPreparedEvent,ApplicationPreparedEvent,ApplicationStoppedEvent等.用于监听springboot生命周期中的各种事件.

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

项目中需要监听用户具体的请求操作,便通过一个拦截器来监听,并继续相应的日志记录 项目构建与Spring Boot,Spring Boot实现一个拦截器很容易. Spring Boot的核心启动类继承WebMvcConfigurerAdapter // 增加拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new RequestLog()); } //这