zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    卡巴斯基呼吁通过国际立法打击网络犯罪 狼人:
    服务流量论Google的那些服务
    字符数组hdu 4552
    方法说明JAVA复习笔记前言:第一节:从注释开始
    新特性版本Impala各版本新特性
    通知准时为什么讲座时间在通知中提前了半个小时
    集合objectjava_collection
    android对象巧用Android网络通信技术,在网络上直接传输对象
    ejb对象2013年 最新面试题
    提示系统启动关于误更改/var下诺干的权限问题,导致系统启动提示The System is running in lowgraphics mode问题解决 By ACReaper
  • 原文地址:https://www.cnblogs.com/aipan/p/7422641.html
Copyright © 2011-2022 走看看