Spring的事件处理

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());
	}
}






posted @ 2016-01-15 21:34  zfyouxi  阅读(225)  评论(0编辑  收藏  举报