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. 基于visual Studio2013解决C语言竞赛题之0506选择排序

     题目

  2. Linux c c++ 开发调试技巧

    看到一篇介绍 linux c/c++ 开发调试技巧的文章,感觉挺使用,哪来和大家分享. 通向 UNIX 天堂的 10 个阶梯Author: Arpan Sen, 高级技术人员, Systems Doc ...

  3. Actor::updateMassFromShapes

    unity报错Actor::updateMassFromShapes: Compute mesh inertia tensor failed for one of the actor's mesh s ...

  4. 学习MongoDB 二:MongoDB加入、删除、改动

    一.简单介绍 MongoDB是一个高性能.开源.无模式的文档型数据库,是当前NoSQL数据库产品中最热门的一种.数据被分组存储在数据集中,被称为一个集合(Collenction)和对于存储在Mongo ...

  5. 解决 RichTextBox 文件格式不对问题

    RichTextBox文件格式不对: 原因:富文本框的LoadFile方法只支持RTF格式的文件或者标准的ASCII文本本档,,我们一般的文本文档是ANSI或者UTF-8的格式,所以,报这个错. 解决 ...

  6. RadioButton控件

    前台代码: <div> <asp:RadioButton ID="RadioButton1" runat="server" GroupName ...

  7. 如何创建C++程序

    下载Microsoft Visual C++ 6.0请点击这里:VC 6.0下载(包括中文版英文版)(支持Win7和XP) 首先,我们要进入Microsoft Visual C++集成开发环境(Int ...

  8. mac忘记登陆密码解决

    重新启动苹果电脑,开机时按住“command”键+“S”键,(普通键盘按住win+s)会进入单用户模式, 出现像DOS一样的提示符 #root>依次输入如下三个命令:(注意空格 注意大小写) f ...

  9. 04-Foundation-NSSet、NSDictionary、block

    目录: 一.NSSet集合 二.NSDictionary字典 三.block代码块 回到顶部 一.NSSet集合 1 NSSet是一个无序的,管理对个对象的集合类,最大特点是集合中不允许出现重复对象, ...

  10. 基于RAF的一个小动画框

    RAF也即是requestAnimationFrame,之前的动画都是基于setTimeout写的,所以为了性能方面的考虑,开始使用requestAnimationFrame写动画. function ...