Spring对事件有一些支持,因为项目须要,所以近期小小研究了下究竟这个怎么能够方便的用在实际项目其中来。

说起事件这个东西,事实上就是借鉴的那个观察者模式。这里面涉及到事件源、事件监听者、事件公布者三个概念。

事件就是当我们改动一些数据之后,可能须要把这些改动后的数据告诉其它模块或者业务,使用事件后。当我改动了数据后。会公布一个事件。

那些关心我数据变化的,仅仅须要继承BasicService而且事件源和我的一样,他就会收到这个事件的通知。

这个,有个弊端就是多个事件源的时候,怎么通知。

以后再优化吧。

先处理起简单的业务再说。慢慢来吧。

直接来样例比較好说一些。须要使用到Spring的jar包。

首先看底层封装的事件源。

package com.mine.event.basic.event;

import java.util.List;

import org.springframework.context.ApplicationEvent;

import com.mine.event.basic.enums.EventTypeEnum;

/**
*
* @author 2014-11-3 下午07:06:20
* @version V1.0
*/
public class BasicEvent extends ApplicationEvent { /** * 序列化ID */
private static final long serialVersionUID = 7519966952568731040L; public BasicEvent(Object object){
super(object);
} private EventTypeEnum eventTypeEnum; /**
* 事件通知的内容列表
*/
private List<? > eventList; /***
* 事件通知内容单个
*/
private Object eventObject; public void setEventList(List<? > eventList) {
this.eventList = eventList;
} public List<?> getEventList() {
return eventList;
} public void setEventTypeEnum(EventTypeEnum eventTypeEnum) {
this.eventTypeEnum = eventTypeEnum;
} public EventTypeEnum getEventTypeEnum() {
return eventTypeEnum;
} public void setEventObject(Object eventObject) {
this.eventObject = eventObject;
} public Object getEventObject() {
return eventObject;
}
}

然后就是事件监听者、事件公布者。

这里设计到一个类中的缘故是方便实现者。不须要实现者写那么多内容。

package com.mine.event.basic.service;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener; import com.mine.event.basic.enums.EventTypeEnum;
import com.mine.event.basic.event.BasicEvent;
/**
*
* @author 2014-11-3 下午07:11:53
* @version V1.0
*/
public abstract class BasicService<T extends BasicEvent> implements ApplicationContextAware,ApplicationListener<BasicEvent>{ public abstract Class fetchCurrentEvent(); private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
} /**
* 添加单个对象并公布事件
* @author 2014-11-5 上午09:15:25
* @param object
*/
public void addSingleObj(Object object){ Object event = getEventObject(object,EventTypeEnum.ADD); applicationContext.publishEvent((ApplicationEvent)event);
}
/** 通过反射实例化对象和设置事件类型
* @author 2014-11-5 上午11:53:39
* @param object
* @param eventTypeEnum 事件类型
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked","finally" })
private Object getEventObject(Object object,EventTypeEnum eventTypeEnum){
//获取构造方法
Object event = null;
try {
Class eventClass = fetchCurrentEvent();
Constructor constructor = fetchCurrentEvent().getConstructor(Object.class);
event = constructor.newInstance(this);
//获取setEventObject方法
Method method = eventClass.getMethod("setEventObject",Object.class);
//调用setEventObject方法
method.invoke(event,object);
//获取设置事件枚举的方法
Method enuMethod = eventClass.getMethod("setEventTypeEnum", EventTypeEnum.class);
enuMethod.invoke(event,eventTypeEnum);
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}finally{
return event;
}
} /***
* 须要实现者完毕的详细事件内容
* @author 2014-11-5 上午09:14:58
* @param event
*/
public abstract void notifyEvent(BasicEvent event); /**
*事件
*/
@Override
public void onApplicationEvent(BasicEvent event) {
String eventString = event.getClass().toString();
String currentString = fetchCurrentEvent().toString();
//同样类型的事件才会进行通知
if (eventString.equals(currentString)) {
notifyEvent(event);
}
}
}

然后就是事件类型,採用枚举的方式,简单的分为添加、改动、删除。

package com.mine.event.basic.enums;
/**
* 事件类型
* @author 2014-11-3 下午07:02:09
* @version V1.0
*/
public enum EventTypeEnum { ADD,//添加
DEL,//删除
MODIFY//改动
}

以下进行样例的演示

首先定义一个实体User
package com.mine.event.entity;

/**
*
* @author 2014-11-3 下午06:59:26
* @version V1.0
*/
public class User { private Integer id; private String name; public int getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public User(Integer id, String name) {
super();
this.id = id;
this.name = name;
} public void setName(String name) {
this.name = name;
} }

然后是事件源

package com.mine.event.event;

import com.mine.event.basic.event.BasicEvent;

/**
* 用户相关事件
* @author 2014-11-3 下午07:06:09
* @version V1.0
*/
public class UserEvent extends BasicEvent{ /** * 序列化ID */
private static final long serialVersionUID = 7117267688533263478L; public UserEvent(Object object) {
super(object);
} }
这个主要是对照用的。
package com.mine.event.event;

import com.mine.event.basic.event.BasicEvent;

public class TEvent extends BasicEvent {

	public TEvent(Object object) {
super(object);
} }

然后是定义一个Service。并且它既是监听者又是公布者。

package com.mine.event.service;

import com.mine.event.basic.enums.EventTypeEnum;
import com.mine.event.basic.event.BasicEvent;
import com.mine.event.basic.service.BasicService;
import com.mine.event.entity.User;
import com.mine.event.event.UserEvent; public class UserService extends BasicService<UserEvent> { /**
* 添加用户
*
* @author 2014-11-3 下午07:18:16
* @param user
*/
public void addUser(User user) {
this.addSingleObj(user);
} /**
* 依据事件类型进行对应的处理
*/
@Override
public void notifyEvent(BasicEvent event) { //假设UserEvent有自己定义的属性或方法。以下须要调用的,则须要强制转换为UserEvent
// UserEvent userEvent = (UserEvent) event; EventTypeEnum typeEnum = event.getEventTypeEnum(); User user = (User)event.getEventObject();
if (user == null) {
return;
}
switch (typeEnum) {
case ADD:
System.out.println("ADD:" + user.getName());
break;
case MODIFY:
System.out.println("MODIFY:" + event.getEventObject());
break;
case DEL:
System.out.println("DEL:" + event.getEventObject());
break;
default:
System.out.println("其他");
break;
}
} @Override
public Class fetchCurrentEvent() {
return UserEvent.class;
}
}

以下的和这个主要是用来对照的,由于这个事件源是TEvent。所以UserEvent事件发生后,UserServiceTemp不会收到通知。

由于BasicService在进行事件通知时会比对事件源是否一样。一样的才会进行通知。
package com.mine.event.service;

import com.mine.event.basic.enums.EventTypeEnum;
import com.mine.event.basic.event.BasicEvent;
import com.mine.event.basic.service.BasicService;
import com.mine.event.entity.User;
import com.mine.event.event.TEvent; public class UserServiceTemp extends BasicService<TEvent>{ /**
* 添加用户
*
* @author 2014-11-3 下午07:18:16
* @param user
* @modificationHistory=========================逻辑或功能性重大变更记录
* @modify by user: {改动人} 2014-11-3
* @modify by reason:{原因}
*/
public void addUser(User user) {
this.addSingleObj(user);
} /**
* 依据事件类型进行对应的处理
*/
public void notifyEvent(BasicEvent event) { //假设UserEvent有自己定义的属性或方法。以下须要调用的,则须要强制转换为UserEvent
// UserEvent userEvent = (UserEvent) event; EventTypeEnum typeEnum = event.getEventTypeEnum(); User user = (User)event.getEventObject();
if (user == null) {
return;
}
switch (typeEnum) {
case ADD:
System.out.println("UserServiceTempADD:" + user.getName());
break;
case MODIFY:
System.out.println("MODIFY:" + event.getEventObject());
break;
case DEL:
System.out.println("DEL:" + event.getEventObject());
break;
default:
System.out.println("其他");
break;
}
} public Class fetchCurrentEvent() {
return TEvent.class;
}
}

以下是Sping的一些配置

<?xml version="1.0" encoding="UTF-8"?

>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
<bean id="userServiceImpl" class="com.mine.event.service.UserService" />
<bean id="userServiceTemp" class="com.mine.event.service.UserServiceTemp" />
</beans>

最后是一个測试类

package com.mine.event.test;

import java.util.Collection;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import com.mine.event.basic.service.BasicService;
import com.mine.event.entity.User;
import com.mine.event.service.UserService; public class TestUserEvent { public static void main(String[] args) { User user = new User(1,"name_1"); ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = applicationContext.getBean("userServiceImpl",UserService.class); userService.addUser(user); Collection<BasicService> collection = applicationContext.getBeansOfType(BasicService.class).values(); //通过Spring能够获得全部载入到Spring上下文中的一个类的子类。
System.out.println("获取BasicService的全部载入到Spring上下文其中的全部子类个数"+collection.size());
}
}

Spring的事件处理的更多相关文章

  1. Spring入门学习笔记(3)——事件处理类

    目录 Spring中的事件处理 Spring内建事件 监听Context事件 Example 自定义Spring事件 Spring中的事件处理 ApplicationContext 是Spring的核 ...

  2. Spring(九)之事件处理

    Spring的核心是ApplicationContext,它管理bean的完整生命周期.ApplicationContext在加载bean时发布某些类型的事件.例如,ContextStartedEve ...

  3. Spring中的事件处理

    文章目录 Spring中的事件处理 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期.当加载 beans 时,ApplicationContext ...

  4. Spring 中的事件处理

    Spring 中的事件处理 Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期.当加载 beans 时,ApplicationContext 发布某些 ...

  5. 01.Spring Ioc 容器

    基本概念 Spring 的 Ioc 容器,通常也称应用上下文.它包含了两个概念 Ioc 和 容器: 容器:顾名思义就是用来装东西的,在 Spring 中容器里盛放的就是各种各样的 Bean.既然装了东 ...

  6. Spring IoC和AOP的介绍

    基于Spring Framework 版本:5.0.2.RELEASE IoC 概念:传统Java开发中,程序通过new主动创建对象实例,而Spring有专门的IoC容器来创建对象,具体来说就是在Sp ...

  7. Spring教程检视阅读

    Spring教程检视阅读 地址 可供参考的教程 <菜鸟学 SSH> <Spring Boot 那些事> <初识 Spring Security> <Sprin ...

  8. Sping框架初步使用1

    Spring核心容器的理论:Spring核心容器就是一个超大工厂,所有的对象都会被当成Spring容器的核心管理对象,Spring把容器中一切对象统称为Bean(只要是一个Java类,Spring就可 ...

  9. Eureka Server启动过程

    前面对Eureka的服务端及客户端的使用均已成功实践,对比Zookeeper注册中心的使用区别还是蛮大的: P:分区容错性(⼀定的要满⾜的)C:数据⼀致性 A:⾼可⽤:CAP不可能同时满⾜三个,要么是 ...

随机推荐

  1. Ant学习实例

    ant   目录(?)[+] Ant学习实例 安装Ant 基础元素 project元素 target元素 property元素 完整示例   Ant学习实例 1.安装Ant 先从http://ant. ...

  2. make报错:"/usr/bin/ld: cannot find -lXXX"

    在编译php时报错如下: # make ... /usr/bin/ld: cannot find -lltdlcollect2: ld returned 1 exit statusmake: *** ...

  3. Technology_Roadmap

    2016年1月23日 前端技术: - HTML CSS JavaScript JQuery 操作系统: - Linux (CentOS) 数据库: - SQLServer MySQL 开源前端框架: ...

  4. Qt同步线程(比较清楚,而且QMutex QMutexLocker QReadWriteLock QSemaphore QWaitCondition 每个都有例子)

    Qt同步线程 我们知道,多线程有的时候是很有用的,但是在访问一些公共的资源或者数据时,需要进行同步,否则会使数据遭到破坏或者获取的值不正确.Qt提供了一些类来实现线程的同步,如QMutex,QMute ...

  5. Qt 智能指针学习(7种QT智能指针和4种std智能指针)

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...

  6. JQuery遍历json数组的3种方法

    这篇文章主要介绍了JQuery遍历json数组的3种方法,本文分别给出了使用each.for遍历json的方法,其中for又分成两种形式,需要的朋友可以参考下 一.使用each遍历 $(functio ...

  7. 2016年会成为Java EE微服务年吗?

    原文  http://www.infoq.com/cn/news/2016/02/javaee-microservices 进入2016年时间还不是很长,让我们回顾下去年年底的一个预言.去年12月,来 ...

  8. 用overflow-y 解决web页面抖动问题

    页面抖动(左右抖动)让人视觉上很不爽.. /** original : php攻城师 http://blog.csdn.net/phpgcs **/ 最开始我也以为是 layout 不一致的原因..后 ...

  9. 软件project师的属性与发展

    工作近十年了.[软件project师] 一直是我职业 title 的中心词,仅仅是前面的修饰语在不断变化,从0基础.中级.高级到资深. 事实上 [软件project师] 是一个非常泛化的定义.工作现实 ...

  10. 用 PS 复制权限

    用 PS 复制权限 我们要把源计算机上的文件权限复制到目的计算机上. get-acl .\s.txt | Export-Clixml sddl.xml 把 s.txt 文件的权限保存到 sddl.xm ...