基于IOC的Java事件框架的设计与实现 Ⅱ

该框架的设计基于IOC思想。关于IOC,具体可见:http://www.csufox.com/spring-ioc.html

不过该框架实现的不是属性注入,而是将触发器-监听器-执行器的绑定由配置文件配置,框架底层实现,实现了控制反转。

该框架取名为XMLEventHandler,意为基于XML文件配置Java事件的处理器。

技术基础:

1. Java对XML文件的读取。XML是一种标记语言,用于各种配置文件和不同语言间交换信息,它只负责信息的存储,而不负责信息的表达(HTML语言是XML的衍化语言,负责网页信息的表达)。本框架采用jdk1.6自带的 org.w3c.dom 包来解析XML文档。具体可见:http://gceclub.sun.com.cn/Java_Docs/html/zh_CN/api/index.html

2. Java反射机制(reflection)。反射机制用于运行中动态地实例化任意类或者调用该类的任意方法。不管网上将反射机制说得多复杂,言简意赅的一句解释就是:Java加载类的路径(字符串),通过无参构造函数来实例化目标对象,或通过方法名调用目标方法(传入参数数组)。概括为四句代码:

 

Object targetClass = Class.forName(classPath).newInstance(); //通过类的路径名来实例化对象
Class<?> cla = targetClass.getClass();    //<>是泛型设计,这里可用通配符?表示
Method m = cla.getMethod(targetMethod,new Class[]{});  //传入方法名和参数类型数组
m.invoke(targetClass, new Object[]{});   //方法执行,传入目标类的实例和参数数组

配置文件命名为:event-config.xml,意为事件配置文件。

event-config.xml 文件初步设计如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <bean id="frame" class="demo.FrameDemo2">
        <component name="calculate">
            <event type="ActionListener" class="event.OnClick" method="onClick"></event>
        </component>
    </bean>
</beans>

XML文件与属性文件不同,属性文件一般是一一映射关系,而XML文件则是一对多的映射关系,本质是树结构。

配置文件解释如下

  • 根节点为beans
  • bean节点的id属性用来唯一地标识一个bean容器(Frame),class属性用来唯一地确定bean所在类的路径。
  • component节点的name属性表示为容器内的组件名,“calculate”是一个button名。
  • event节点的type属性表示监听器的类型,class表示事件执行器的完整路径,method表示执行器的方法名。

结构如下:(只包含前三个包,demo包用于测试,event包用于定义远程事件执行方法)

image

  • 下面开始框架的详细代码实现:  

     

    XMLReader.java

    作用:用于对xml文件进行处理,以及实例化bean容器,比如Frame,Panel,Window。

package com.csufox.util;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.csufox.event.BeanFactory;
import com.sun.org.apache.xerces.internal.parsers.DOMParser;

public class XMLReader {
    private Element rootNode;
    public XMLReader(String fileName){
        DOMParser parse = new DOMParser();
        try {
            parse.parse(fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        Document doc = parse.getDocument();   //预处理xml文件,转换为doc文档类
        rootNode = doc.getDocumentElement();
    }
    public Object getBean(String id){   //得到指定容器的实例
        Object obj = null;
        NodeList beanNodeList = rootNode.getElementsByTagName("bean");
        for(int i=0;i<beanNodeList.getLength();i++) {
            Element beanNode = (Element) beanNodeList.item(i);
            if(beanNode.getAttribute("id").equals(id)){
                obj = BeanFactory.create(beanNode);
            }
        }
        return obj;
    }
}

 

BeanFactory.java

作用:bean工厂,利用简单工厂模式,传入不同的参数来得到不同的bean容器,初始化的工作交由工厂处理。

package com.csufox.event;

import java.beans.Expression;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class BeanFactory {
    public static Object create(Element beanNode){ //工厂静态方法
        Object bean = null;
        try {
            bean = Class.forName(beanNode.getAttribute("class")).newInstance();
            NodeList componentNodeList = beanNode.getElementsByTagName("component");
            for(int i=0;i<componentNodeList.getLength();i++){
                Element componentNode = (Element)componentNodeList.item(i);
                String componentName = componentNode.getAttribute("name");

                String firstChar = componentName.charAt(0) + "";
                String newFirstChar = firstChar.toUpperCase();
                String methodName = "get" + componentName.replaceFirst(firstChar, newFirstChar);               //得到get函数,进而得到容器内的组件,如Button

                Expression e=new Expression(bean,methodName,null);
                e.execute();
                Object component = e.getValue(); //Expression用于执行给定类中的指定方法,并得到返回值。这是Java反射机制的一种替代方案,执行效率更高。

                NodeList eventNodeList = componentNode.getElementsByTagName("event");
                for(int j=0;j<eventNodeList.getLength();j++){
                    Element eventNode = (Element)eventNodeList.item(j);
                    EventHandler.handle(bean,component,eventNode);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}

EventHandler.java

作用:事件处理器,用于将容器内的组件添加事件监听器。

package com.csufox.event;

import java.lang.reflect.Method;

import org.w3c.dom.Element;

import com.csufox.listener.SingletonActionListener;

public class EventHandler{
    private static SingletonActionListener listener = null;

    public static void handle(Object bean,Object component,Element eventNode){
        String listenerType = eventNode.getAttribute("type");
        if(listenerType.equals("ActionListener")){
            listener = SingletonActionListener.getInstance(bean,component,eventNode);
        }
        Class<?> componentClass = component.getClass();
        String addListener = "add" + listenerType;   //得到添加事件监听器的方法名
        try {
            Class<?> name = Class.forName("java.awt.event."+listenerType);
            Method method = componentClass.getMethod(addListener,name);
            method.invoke(component,listener);  //反射机制执行方法,可用Statement类替代
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

更多内容:www.csufox.com

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值