关于JAVA中事件分发和监听机制实现的代码实例

简介:

文章标题:关于JAVA中事件分发和监听机制实现的代码实例

文章地址: http://blog.csdn.net/5iasp/article/details/37054171

作者: javaboy2012
Email:yanek@163.com
qq:    1046011462

 

 

一、场景假设

假设有博客系统中需要实现如下功能:

系统中用户发布文章,修改文章,删除文章时,需要一些相关的操作需要执行。


发布文章后,给好友发送邮件通知,给用户加积分,对文章做全文索引。
修改文章后,给好友发送邮件修改通知,给用户加积分,对文章重新做全文索引。
删除文章后,给好友发送邮件修改通知,给用户减少积分,对文章重新做全文索引。

 

二、相关的概念解析

   分析如上场景,可以采用事件分发和监听机制来实现。

 
  事件分发和监听有如下几个概念:


 事件源:触发事件的对象 如上场景中我们把实体对象作为事件源,发布的文章就是事件源

 事件: 对事件源的操作产生事件,例如 发表文章 修改文章,删除文章这些操作就会触发相关的 文章被发表事件,文章被删除事件,文章被修改事件

 事件监听器:对事件源各种事件触发执行行为的抽象,包括接口和若干实现类。

    比如: 接口需要定义事件源相关事件触发时需要实现的操作接口。

 事件分发器:事件分发器主要处理事件的分发和事件监听器的管理,注册和删除事件监听器等。   

 

三、 代码示例

 

项目结构:

 


根据上述概念相关代码如下:


  包括如下代码

  1. 博客文章类  属于事件源

package com.yanek.event;
/**
 * 博客文章
 * @author Administrator
 *
 */
public class Entry {
	
	
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	private long id; // 编号
	private String name; //标题
	
}


 

2. 博客文章事件类 属于事件对象

其中定义了事件的类型和事件源,事件参数

package com.yanek.event;

import java.util.Collections;
import java.util.Date;
import java.util.Map;
/**
 * 博客文章事件
 * @author Administrator
 *
 */
public class EntryEvent

{

	public static final int ENTRY_ADDED = 100; //事件类型:博客文章被创建
	public static final int ENTRY_DELETED = 101;//事件类型:博客文章被删除
	public static final int ENTRY_MODIFIED = 102;//事件类型:博客文章被修改

	private int eventType; //事件类型
	private Entry entry; //博客文章对象
	private Date date; //事件触发日期
	private Map params; //事件辅助参数

	public EntryEvent(int eventType, Entry entry, Map params) {
		this.eventType = eventType;
		this.entry = entry;
		this.params = params != null ? Collections.unmodifiableMap(params)
				: null;
		date = new Date();
	}

	public int getEventType() {
		return eventType;
	}

	public Entry getEntry() {
		return entry;
	}

	public Map getParams() {
		return params;
	}

	public Date getDate() {
		return date;
	}
}


 

3. 事件监听器接口和实现类:

定义各种事件发生时需要处理的接口方法

package com.yanek.event;
/**
 * 博客文章监听器接口
 * @author Administrator
 *
 */
public interface EntryListener
{
    /**
     * 博客文章被创建
     * @param entryevent
     */
    public abstract void entryAdded(EntryEvent entryevent); 
    
    /**
     * 博客文章被删除
     * @param entryevent
     */

    public abstract void entryDeleted(EntryEvent entryevent);
    
    
    /**
     * 博客文章被修改
     * @param entryevent
     */
    public abstract void entryModified(EntryEvent entryevent);

}


 

事件监听器接口的实现类:


   实现场景中的三类操作,监听器接口实现包括如下三个类实现

  
  IndexManager 索引管理器类
  ScoreManager 积分管理器类
  EmailManager 邮件管理器类

  三个类都实现监听器接口EntryListener。具体代码如下:

 package com.yanek.event;



/**
 * 邮件管理器
 * @author Administrator
 *
 */
public class EmailManager implements EntryListener{

	@Override
	public void entryAdded(EntryEvent entryevent) {

		System.out.println("EmailManager 处理 博客文章被创建事件。");
		
	}
	
	@Override
	public void entryDeleted(EntryEvent entryevent) {

		System.out.println("EmailManager 处理 博客文章被删除事件。");
	}
	@Override
	public void entryModified(EntryEvent entryevent) {
	
		System.out.println("EmailManager 处理 博客文章被修改事件。");
		
	}


}



package com.yanek.event;
/**
 * 索引管理器
 * @author Administrator
 *
 */
public class IndexManager implements EntryListener {

	@Override
	public void entryAdded(EntryEvent entryevent) {


		System.out.println("IndexManager 处理 博客文章被创建事件。");
		
	}

	@Override
	public void entryDeleted(EntryEvent entryevent) {
		// TODO Auto-generated method stub
		System.out.println("IndexManager 处理 博客文章被删除事件。");
		
	}

	@Override
	public void entryModified(EntryEvent entryevent) {
		// TODO Auto-generated method stub
		System.out.println("IndexManager 处理 博客文章被修改事件。");
	}

}



package com.yanek.event;
/**
 * 积分管理器
 * @author Administrator
 *
 */
public class ScoreManager implements EntryListener {

	@Override
	public void entryAdded(EntryEvent entryevent) {
		System.out.println("ScoreManager 处理 博客文章被创建事件。");
		
	}

	@Override
	public void entryDeleted(EntryEvent entryevent) {
		// TODO Auto-generated method stub
		System.out.println("ScoreManager 处理 博客文章被删除事件。");
	}

	@Override
	public void entryModified(EntryEvent entryevent) {
		// TODO Auto-generated method stub
		
		System.out.println("ScoreManager 处理 博客文章被修改事件。");
		
	}

}


4. 博客文章事件分发器类

 

package com.yanek.event;

import java.util.ArrayList;
/**
 * 博客文章事件分发器
 * @author Administrator
 *
 */
public class EntryEventDispatcher {

	private static EntryEventDispatcher instance = new EntryEventDispatcher();
	private ArrayList listeners=new ArrayList();

	public static EntryEventDispatcher getInstance() {
		return instance;
	}

	private EntryEventDispatcher() {
		
		String[] observers = PropertyMgr.getProperty("observers").split(",");
		for(String s : observers) {
			
			System.out.println(s);
			try {
				this.addListener((EntryListener)(Class.forName(s).newInstance()));
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		}
		

	}

	public synchronized void addListener(EntryListener listener) {
		System.out.println(":"+listener);
		if (listener == null) {
			System.out.println(":"+listener);
			throw new NullPointerException();
		} else {
			listeners.add(listener);
			return;
		}
	}

	public synchronized void removeListener(EntryListener listener) {
		listeners.remove(listener);
	}

	public void dispatchEvent(EntryEvent event) {
		// System.out.println("msgDispatchEvent");
		int eventType = event.getEventType();
		long t1=System.currentTimeMillis();
		System.out.println("kaishi="+t1);
		for (int i = 0; i < listeners.size(); i++) {
			try {
				EntryListener listener = (EntryListener) listeners.get(i);
				String name = listener.getClass().getName();
				name = name.substring(name.lastIndexOf('.') + 1);

				switch (eventType) {
				case EntryEvent.ENTRY_ADDED: // 创建博客文章
					listener.entryAdded(event);
					break;

				case EntryEvent.ENTRY_DELETED: // 删除博客文章
					listener.entryDeleted(event); 
					break;

				case EntryEvent.ENTRY_MODIFIED: //修改 博客文章
					listener.entryModified(event);
					break;

				}

			} catch (Exception e) {
				// logger.error(e);
			}

		}
		
		System.out.println("cost time="+(System.currentTimeMillis()-t1));

		// Profiler.end("msgDispatchEvent");
	}
}


5. 博客文章管理器类

 


 

package com.yanek.event;

/**
 * 博客文章管理器
 * @author Administrator
 *
 */

public class EntryManager {

 /**
  * @param args
  */
 public static void main(String[] args) {


  EntryManager eventManager=new EntryManager();
  Entry entry=new Entry();
  entry.setId(1);
  entry.setName("test");
  
  eventManager.addEntry(entry);  //创建
  
  eventManager.modifyEntry(entry); //修改
  
  eventManager.deleteEntry(entry); //删除
 }
 
 public void addEntry(Entry entry) {
  System.out.println("add entry ...id="+entry.getId());
  
  // 事件分发
  EntryEvent event = new EntryEvent(EntryEvent.ENTRY_ADDED, entry, null);
  EntryEventDispatcher.getInstance().dispatchEvent(event);
  
 }
 
 public void deleteEntry(Entry entry) {
  System.out.println("delete entry ...id="+entry.getId());
  
  // 事件分发
  EntryEvent event = new EntryEvent(EntryEvent.ENTRY_DELETED, entry, null);
  EntryEventDispatcher.getInstance().dispatchEvent(event);
  
 }
 
 public void modifyEntry(Entry entry) {
  System.out.println("modify entry ...id="+entry.getId());
  // 事件分发
  EntryEvent event = new EntryEvent(EntryEvent.ENTRY_MODIFIED, entry, null);
  EntryEventDispatcher.getInstance().dispatchEvent(event);
  
 }

}


6. 辅助工具类:

  package com.yanek.event;

import java.io.IOException;
import java.util.Properties;

public class PropertyMgr {
 private static Properties props = new Properties();
 
 static {
  try {
   props.load(PropertyMgr.class.getClassLoader().getResourceAsStream("com/yanek/event/config.properties"));
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
 
 public static String getProperty(String key) {
  return props.getProperty(key);
 }
}


 7.相关配置文件:

 

配置分发器处理时需要的监听器实现类的列表。

config.properties

内容如下:

observers=com.yanek.event.IndexManager,com.yanek.event.ScoreManager,com.yanek.event.EmailManager

 

 

 四 测试运行结果:

 

执行: EntryManager 即可看到效果:

 

add entry ...id=1
com.yanek.event.IndexManager
:com.yanek.event.IndexManager@3d3c53
com.yanek.event.ScoreManager
:com.yanek.event.ScoreManager@3d3f58
com.yanek.event.EmailManager
:com.yanek.event.EmailManager@3d425b
kaishi=1404547648004
IndexManager 处理 博客文章被创建事件。
ScoreManager 处理 博客文章被创建事件。
EmailManager 处理 博客文章被创建事件。
cost time=1
modify entry ...id=1
kaishi=1404547648006
IndexManager 处理 博客文章被修改事件。
ScoreManager 处理 博客文章被修改事件。
EmailManager 处理 博客文章被修改事件。
cost time=1
delete entry ...id=1
kaishi=1404547648007
IndexManager 处理 博客文章被删除事件。
ScoreManager 处理 博客文章被删除事件。
EmailManager 处理 博客文章被删除事件。
cost time=0

 

五。关于该方案系统如何实现灵活扩展


假设有如下需求增加了,比如 发表文章,修改文章,删除文章后需要需要给好友发短信通知或其他相关功能,则只需要再写一个监听器的实现类,加入到配置文件中即可。

具体就不写代码了,大家可以自己加上测试。

 

 
六、关于资源下载:

地址: http://download.csdn.net/detail/5iasp/7596885

 

 本篇博文参加了CSDN博文大赛,如果您觉得这篇博文不错,希望您能帮我投一票,谢谢!

投票地址:http://vote.blog.csdn.net/Article/Details?articleid=37054171

学习是一种信仰,分享是一种美德

 

 

 

 

 

目录
相关文章
|
4天前
|
Java
【专栏】Java中的反射机制与应用实例
【4月更文挑战第27天】本文探讨了Java反射机制,该机制允许程序在运行时获取类信息、动态创建对象、调用方法和访问属性。反射通过Class、Constructor、Method和Field类实现。文中列举了反射的应用场景,如动态创建对象、调用方法、访问属性和处理注解,并提供了相关实例代码演示。
|
1天前
|
Java Spring
Java 效率编码 必备插件 Lombok 让代码更优雅
该内容是一个关于Lombok插件的教程摘要:介绍了Lombok用于减少Java开发中的模板代码,提升效率;讲解了如何在IntelliJ IDEA中安装Lombok插件,以及在pom.xml中添加依赖;并提到了@Data注解能自动生成getter/setter、equals、hashCode和toString方法,@Slf4j注解自动处理日志,@Builder用于构建对象,以及@AllArgsConstructor和@NoArgsConstructor注解生成构造函数。还鼓励探索更多Lombok的注解用法。
|
1天前
|
Java 关系型数据库 测试技术
Java代码一键生成数据库文档(案例详解)
Screw是一个自动化数据库文档生成工具,能根据数据库表结构快速生成简洁、多格式(HTML、Word、Markdown)的文档,支持MySQL、MariaDB等多数据库。它使用Freemarker模板,允许用户自定义样式。依赖包括HikariCP数据库连接池和对应JDBC驱动。通过在Java代码或Maven插件中配置,可方便生成文档。示例代码展示了如何在测试用例中使用Screw。文档效果依赖于数据库中的表和字段注释。
|
1天前
|
NoSQL Java API
java一行代码实现RESTFul接口
Spring Data REST是构建在Spring Data之上的库,可自动将repository转换为REST服务,支持JPA、MongoDB、Neo4j、GemFire和Cassandra。无需手动创建Service和Controller层。要开始,需配置JPA数据源,创建实体类和Repository接口。快速实现REST接口,只需引入spring-boot-starter-data-rest Maven依赖,并在Repository接口上添加@RepositoryRestResource注解。
|
2天前
|
Java 程序员 开发者
深入理解Java并发编程:线程同步与锁机制
【4月更文挑战第30天】 在多线程的世界中,确保数据的一致性和线程间的有效通信是至关重要的。本文将深入探讨Java并发编程中的核心概念——线程同步与锁机制。我们将从基本的synchronized关键字开始,逐步过渡到更复杂的ReentrantLock类,并探讨它们如何帮助我们在多线程环境中保持数据完整性和避免常见的并发问题。文章还将通过示例代码,展示这些同步工具在实际开发中的应用,帮助读者构建对Java并发编程深层次的理解。
|
2天前
|
敏捷开发 机器学习/深度学习 Java
Java中的异常处理机制深入理解与实践:持续集成在软件测试中的应用探索自动化测试在敏捷开发中的关键作用
【4月更文挑战第29天】在Java编程中,异常处理是一个重要的概念。它允许开发者在程序执行过程中遇到错误或异常情况时,能够捕获并处理这些异常,从而保证程序的稳定运行。本文将详细介绍Java中的异常处理机制,包括异常的分类、异常的处理方式以及自定义异常等内容。 【4月更文挑战第29天】 随着敏捷开发和DevOps文化的兴起,持续集成(CI)已成为现代软件开发周期中不可或缺的一环。本文将探讨持续集成在软件测试领域内的关键作用、实施策略以及面临的挑战。通过对自动化构建、测试用例管理、及时反馈等核心要素的详细分析,揭示持续集成如何提高软件质量和加速交付过程。 【4月更文挑战第29天】 在当今快速发
|
3天前
|
安全 Java 测试技术
利用Java反射机制提高Spring Boot的代码质量:概念与实战
【4月更文挑战第29天】Java反射机制提供了一种强大的方法来在运行时检查或修改类和对象的行为。在Spring Boot应用中,合理利用反射可以提高代码的灵活性和可维护性。本篇博客将探讨Java反射的核心概念,并展示如何通过反射提高Spring Boot项目的代码质量。
16 0
|
4天前
|
Java API
Java包机制及JavaDoc
Java包机制及JavaDoc
|
5天前
|
安全 Java
【JAVA】Java并发编程中的锁升级机制
【JAVA】Java并发编程中的锁升级机制
|
5天前
|
Java 编译器 开发者
【JAVA】为什么代码会重排序
【JAVA】为什么代码会重排序