spring中自定义Event事件的使用和浅析

在我目前接触的项目中,用到了许多spring相关的技术,框架层面的spring、spring mvc就不说了,细节上的功能也用了不少,如schedule定时任务、Filter过滤器、 interceptor拦截器等等,而这一篇我要说的是spring Event自定义事件,目前的项目中似乎没怎么用,但是这一项技术貌似还蛮重要,所以也不能不掌握。

对于事件驱动模型的解释和理解,我觉得有一篇博客里说的非常好,尤其是在解释这个关系的时候,举的交通信号灯的例子非常贴切,这里就引用做一个简单的解释:

事件驱动模型也就是我们常说的观察者,或者发布-订阅模型;理解它的几个关键点:

1. 首先是一种对象间的一对多的关系;最简单的如交通信号灯,信号灯是目标(一方),行人注视着信号灯(多方);

2. 当目标发送改变(发布),观察者(订阅者)就可以接收到改变;

3. 观察者如何处理(如行人如何走,是快走/慢走/不走,目标不会管的),目标无需干涉;所以就松散耦合了它们之间的关系。

引用的原文地址:http://xls9577087.iteye.com/blog/2121752(这篇文章中还讲解了有序监听和无序监听、异步事件等等,有兴趣的也可以去那里了解学习一下)

当我们对事件驱动有一个简单的理解之后,就能大概知道它应该什么时候用,然后再来研究它该怎么用,单一的文字或许不太容易解释,还是先把代码弄上来,然后再结合起来解释。

首先自定义一个事件,需要继承ApplicationEvent类,相当于安装了一个没有通电,没有灯光的信号灯,需要具有信号灯的基本特征。

package springTest5;
import org.springframework.context.ApplicationEvent;
public class EventTest extends ApplicationEvent {
    private static final long serialVersionUID = 1L;
    private String message;
    public EventTest(Object source, String message) {
        super(source);
        this.message = message;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

然后再创建一个监听类,相当于行人(不管是否使用交通工具),需要实现ApplicationListener接口,并且重写onApplicationEvent方法,可以理解成这个行人需要看信号灯,并且能理解信号灯的意思才行。否则不看信号灯跟没有信号灯没有区别,看了不理解也没用。

package springTest5;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class ListenerTest1 implements ApplicationListener<EventTest> {
    public void onApplicationEvent(EventTest event) {
        System.out.println("test1:" + event.getMessage());
    }
}

这里的注解就只是简单的声明一个bean,应该不需要太多的解释。

那么第三步自然是需要一个控制信号灯变化的东西,相当于是给他接好电线,给他一个正常变换红黄绿的程序和电路。

package springTest5;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
@Component
public class EventPbulish {
    @Autowired
    ApplicationContext context;
    public void publish(String message) {
        context.publishEvent(new EventTest(this, message));
    }
}

到这里,实际上已经写完了,但是呢很明显,我们合理没有配置文件,那么这里的注解也是不能被spring使用的,纯粹是个摆设,所以还需要一个配置文件,或者说相当于配置文件的配置类,要让相关的类生效。

package springTest5;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("springTest5")
public class ConfigTest {

}

对于这里两个注解的意思,前几天的文章曾多次解释,因此这里便不说了,真有不懂得,可以翻一下前几天的博客。

走到这里,相当于我们创建好了一个可以正常运行的信号灯,创建好了一个正常的行人,但是呢都是静止不动的,我们需要让他动起来,也就是main方法的测试,相当于让行人开始看灯,让电路开始通电。

package springTest5;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigTest.class);
        EventPbulish eventPbulish = context.getBean(EventPbulish.class);
        eventPbulish.publish("zhangsan");
        context.close();
    }
}

运行main方法后结果如下:

根据上边的代码可以知道代表这个事件正常运行了,也就是信号灯正常发出了光,行人正常接收到了消息。

那么还有一个细节在于,信号灯对行人,是一对多的关系,那么这里的事件是否确实如此呢?为了验证,我便再写一个监听,再new一个行人,其他一切不变。

package springTest5;
import org.springframework.context.ApplicationListener;
@Component
public class ListenerTest2 implements ApplicationListener<EventTest> {
    public void onApplicationEvent(EventTest event) {
        System.out.println("tst2:" + event.getMessage());
    }
}

再次运行main方法,结果如下:‘

很明显,两个行人都正常接收到了信号灯的信号。

那么,根据上边一开始的解释,再加上之后的例子,我们应该大概知道了这里的一个完整的事件包含些什么内容:即要有目标,也就是一个事件;还要有接受目标信息的对象,也就是一种监听;还要有改变或者说发出信息的一个控制体。

到这里基本上就算是完工了,这算是最简单的实现方式,像一些细节上的,把配置类改配置文件等等,都可以自己适当的变型。

在结尾处,结合@PropertySource注解,我把上边的列子做了个小小的变型,模拟一个找人的广播,喊一个人的名字,然后听到的人进行相应的回答。

这个例子和上边的不同在于,增加了一个properties配置,用来给接收对象初始化名称,顺便练习@PropertySource注解。

name1=zhangsan
name2=lisi

然后修改了一下监听类,从properties文件中获取自己的名字。

package springTest5;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.stereotype.Component;
@Component
@PropertySource("test.properties")
public class ListenerTest1 implements ApplicationListener<EventTest> {
    @Value("${name1}")
    String name;

    public void onApplicationEvent(EventTest event) {
        if (event.getMessage().equals(name)) {
            System.out.println("you need to find " + event.getMessage() + ",yes, I‘am " + name);
        } else {
            System.out
                .println("you need to find " + event.getMessage() + ",but I‘am not " + event.getMessage() + ",I‘am " + name);
        }
    }

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyConfigure() {
        return new PropertySourcesPlaceholderConfigurer();
    }

}

其中propertyConfigure()是必须的,只有写了这个才能正产刚从properties中获取数据,但是经过测试,这一段代码只需要有一个地方出现了就可以,因此第二个监听类就不用再写:

package springTest5;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Component
@PropertySource("test.properties")
public class ListenerTest2 implements ApplicationListener<EventTest> {
    @Value("${name2}")
    String name;
    public void onApplicationEvent(EventTest event) {
        if (event.getMessage().equals(name)) {
            System.out.println("you need to find " + event.getMessage() + ",yes, I‘am" + name);
        } else {
            System.out
                .println("you need to find " + event.getMessage() + ",but I‘am not " + event.getMessage() + ",I‘am " + name);
        }
    }
}

在运行之前的main方法后,结果如下:

这个例子已经打包上传,有兴趣的可以看看,其中只有springTest5这个包里是这个例子,其他几个包里的内容则是对前几天的博文中对profile等技术点的练习,有兴趣的也可以看看。

http://download.csdn.net/detail/tuzongxun/9711034

时间: 2024-10-16 15:04:35

spring中自定义Event事件的使用和浅析的相关文章

Spring中ApplicationContext对事件的支持

Spring中ApplicationContext对事件的支持 ApplicationContext具有发布事件的能力.这是因为该接口继承了ApplicationEventPublisher接口.Spring中与事件有关的接口和类主要包括ApplicationEvent.ApplicationListener.定义一个事件的类需要继承ApplicationEvent或者ApplicationContextEvent抽象类,该抽象类中只有一个构造函数,并 且带有一个Object类型的参数作为事件源

【好文推荐】Spring中ApplicationContext的事件机制

ApplicationContext事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext 事件处理.如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被 触发. Spring的事件框架有如下两个重要的成员: ApplicationEvent:

JavaScript中的Event事件对象详解

JavaScript事件[event] 在JavaScript中对于事件来讲,首先,我们需要了解这样几个概念:事件:事件处理程序:事件类型:事件流:事件冒泡:事件捕获:事件对象:浏览器内核:事件绑定:事件方面的性能优化(事件委托.移除事件处理程序):常见的浏览器兼容问题等. 什么是事件event: JavaScript事件是:浏览器.文档(document)窗口中的发生的特定的交互瞬间:而JavaScript和HTML之间的交互行为就是通过事件来触发的. 事件处理程序: 事件处理程序:我们用户在

javascript中window.event事件用法详解

转自http://www.jb51.net/article/32564.htm描述 event代表事件的状态,例如触发event对象的元素.鼠标的位置及状态.按下的键等等. event对象只在事件发生的过程中才有效. event的某些属性只对特定的事件有意义.比如,fromElement 和 toElement 属性只对 onmouseover 和 onmouseout 事件有意义. 例子下面的例子检查鼠标是否在链接上单击,并且,如果shift键被按下,就取消链接的跳转. 复制代码代码如下: <

spring中自定义注解(annotation)与AOP中获取注解

一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. package me.lichunlong.spring.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.R

Laravel框架中的event事件操作

有时候当我们单纯的看 Laravel 手册的时候会有一些疑惑,比如说系统服务下的授权和事件,这些功能服务的应用场景是什么,其实如果没有经历过一定的开发经验有这些疑惑是很正常的事情,但是当我们在工作中多加思考会发现有时候这些服务其实我们一直都见过.下面就事件.事件监听举一个很简单的例子你就会发现. ? 这个例子是关于文章的浏览数的实现,当用户查看文章的时候文章的浏览数会增加1,用户查看文章就是一个事件,有了事件,就需要一个事件监听器,对监听的事件发生后执行相应的操作(文章浏览数加1),其实这种监听

Spring中的ApplicationContext事件机制

ApplicationContext的事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListerner接口来实现. 1. 创建EmailEvent public class EmailEvent extends ApplicationEvent{ private String address; private String text; public EmailEvent(Object source) { super(source); } publi

自定event事件之全局初始化中自动触发(二)

利用(一)组件:Y_GLOBAL_EVENT 场景:界面加载后在COMPONENTCONTROLLER触发自定义event事件 首先要搞懂WebDynpro启动时的hokeMethod执行顺序如下图: 从上至下,依次进行 从执行顺序中可以看出加载完VIEW视图之后,最后会执行COMPONENTCONTROLLER中的一个叫WDDOPOSTPROCESSING方法, 所以我们可以利用该方法将触发event. METHOD wddopostprocessing . wd_this->fire_tes

Spring 中的事件机制

说到事件机制,可能脑海中最先浮现的就是日常使用的各种 listener,listener去监听事件源,如果被监听的事件有变化就会通知listener,从而针对变化做相应的动作.这些listener是怎么实现的呢?说listener之前,我们先从设计模式开始讲起. 观察者模式 观察者模式一般包含以下几个对象: Subject:被观察的对象.它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法notify().目标类可以是接口,也可以是抽象类或具体类. ConcreteSubject:具体的