`
z75148885
  • 浏览: 191414 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

利用反射实现类的动态加载(程序改正)

阅读更多
原有的http://blog.csdn.net/bromon/上程序未能通过,本文增加之,谢谢原作者:
最近在成都写一个移动增值项目,俺负责后台server端。功能很简单,手机用户通过GPRS打开Socket与服务器连接,我则根据用户传过来的数据做出响应。做过类似项目的兄弟一定都知道,首先需要定义一个类似于MSNP的通讯协议,不过今天的话题是如何把这个系统设计得具有高度的扩展性。由于这个项目本身没有进行过较为完善的客户沟通和需求分析,所以以后肯定会有很多功能上的扩展,通讯协议肯定会越来越庞大,而我作为一个不那么勤快的人,当然不想以后再去修改写好的程序,所以这个项目是实践面向对象设计的好机会。

//首先定义一个接口来隔离类:
public interface Operator
{
// public java.util.List act(java.util.List params);
public java.util.List act(String content,String content2,java.util.List params);
}

根据设计模式的原理,我们可以为不同的功能编写不同的类,每个类都继承Operator接口,客户端只需要针对Operator接口编程就可以避免很多麻烦。比如这个类:
import java.util.*;
public class Success implements Operator
{
public static void main(String[] args) {
List list = new ArrayList();
list.add("Success3");
Operator op = new Success();
System.out.println("act===" + op.act("Success1", "Success2", list));
}
// public java.util.List act(java.util.List params)
public java.util.List act(String content, String content2,
java.util.List params) {
List result = new ArrayList();
result.add(content);
result.add(content2);
result.add(params);
return result;
}
}
同样,也可以写另一个类:
import java.util.*;
public class Load implements Operator
{
public static void main(String[] args) {
List list = new ArrayList();
list.add("Load3");
Operator op = new Load();
System.out.println("act===" + op.act("Load1", "Load2", list));
}
// public java.util.List act(java.util.List params)
public java.util.List act(String content, String content2,
java.util.List params)
{
List result = new ArrayList();
result.add(content);
result.add(content2);
result.add(params);
return result;
}
}
我们还可以写其他很多类,但是有个问题,接口是无法实例化的,我们必须手动控制具体实例化哪个类,这很不爽,如果能够向应用程序传递一个参数,让自己去选择实例化一个类,执行它的act方法,那我们的工作就轻松多了。
很幸运,我使用的是Java,只有Java才提供这样的反射机制,或者说内省机制,可以实现我们的无理要求。编写一个配置文件emp.properties:

#成功响应

1000=Success

#向客户发送普通文本消息

2000=Load

#客户向服务器发送普通文本消息

3000=Store

文件中的键名是客户将发给我的消息头,客户发送1000给我,那么我就执行Success类的act方法,类似的如果发送2000给我,那就执行Load类的act方法,这样一来系统就完全符合开闭原则了,如果要添加新的功能,完全不需要修改已有代码,只需要在配置文件中添加对应规则,然后编写新的类,实现act方法就ok,即使我弃这个项目而去,它将来也可以很好的扩展。这样的系统具备了非常良好的扩展性和可插入性。
下面这个例子体现了动态加载的功能,程序在执行过程中才知道应该实例化哪个类:
import java.lang.reflect.*;
import java.util.Properties;
import java.io.FileInputStream;
import java.util.List;
//这个程序是针对Operator编程的,所以无需做任何修改,直接提供Load和Store类,就可以支持2000、3000做参数的调用
//有了这样的内省机制,可以把接口的作用发挥到极至,设计模式也更能体现出威力,而不仅仅供我们饭后闲聊。
public class TestReflect
{
//加载配置文件,查询消息头对应的类名
private String loadProtocal(String header)
{
String result=null;
try
{
Properties prop=new Properties();
// FileInputStream fis=new FileInputStream("emp.properties");
// id = prop.getProperty(idString);
// prop.load(fis);
// fis.close();
prop.load(getTCL().getResourceAsStream("emp.properties"));
result=prop.getProperty(header);
}catch(Exception e)
{
System.out.println(e);
}
return result;
}
private static ClassLoader getTCL() throws IllegalAccessException,
InvocationTargetException {
Method method = null;
try {
method = Thread.class.getMethod("getContextClassLoader", null);
} catch (NoSuchMethodException e) {
return null;
}
return (ClassLoader)method.invoke(Thread.currentThread(), null);
}

//针对消息作出响应,利用反射导入对应的类
public String response(String header,String content,String content2,List list)
{
String result=null;
String s=null;
try
{
/*
* 导入属性文件emp.properties,查询header所对应的类的名字
* 通过反射机制动态加载匹配的类,所有的类都被Operator接口隔离
* 可以通过修改属性文件、添加新的类(继承MsgOperator接口)来扩展协议
*/
s="org.bromon.reflect."+this.loadProtocal(header).trim();
//加载类
System.out.println("s==="+s);//打印 s===org.bromon.reflect.Success
Class c=Class.forName(s);
//java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类
// Method m[] = c.getDeclaredMethods();//
// for (int i = 0; i < m.length; i++)//
// System.out.println(m[i].toString());
// 打印 public java.util.List org.bromon.reflect.Success.act(java.util.List)
//创建类的事例
Operator mo=(Operator)c.newInstance();
System.out.println("mo==="+mo);
//构造参数列表
Class params[]=new Class[3];
// params[0]=Class.forName("java.util.List");
params[0]=Class.forName("java.lang.String");
params[1]=Class.forName("java.lang.String");
params[2]=Class.forName("java.util.List");
System.out.println("params[0]==="+params[0]);
// //查询act方法
Method m=c.getMethod("act",params);
System.out.println("method=="+m.toString());
Object[] args=new Object[3];
args[0]=content;
args[1]=content2;
args[2]=list;
// //调用方法并且获得返回
Object returnObject=m.invoke(mo,args);//这个地方出问题了,抛异常~~~~
// System.out.println("returnObject==="+returnObject);
List result2 = (List)returnObject;
result = (String)result2.get(0);
System.out.println("result2=="+result2);
//
}catch(Exception e)
{
System.out.println("Handler-response:"+e);//Handler-response:java.lang.IllegalArgumentException: argument type mismatch
//IllegalArgumentException - 如果该方法是实例方法,且指定对象参数不是声明基础方法的类或接口(或其中的子类或实现程序)的实例;
//如果实参和形参的数量不相同;如果基本参数的解包转换失败;或者如果在解包后,无法通过方法调用转换将参数值转换为相应的形参类型。
}
return result;
}
public static void main(String args[])
{
TestReflect tr=new TestReflect();
List list = new java.util.ArrayList();
list.add("测试List");
tr.response("2000","Load1","Load2",list);//1000是Success,2000是Load
tr.response("1000","Success1","Success2",list);//1000是Success,2000是Load

}
}
测试一下,run一下TestReflect类,打印内容有,great!!
result2==[Load1, Load2, [测试List]]
result2==[Success1, Success2, [测试List]]
这个程序是针对Operator编程的,所以无需做任何修改,直接提供Load和Store类,就可以支持2000、3000做参数的调用。
有了这样的内省机制,可以把接口的作用发挥到极至,设计模式也更能体现出威力,而不仅仅供我们饭后闲聊.
分享到:
评论

相关推荐

    利用反射实现类的动态加载

    ### 利用反射实现类的动态加载 #### 反射技术简介 反射是Java语言提供的一种强大特性,允许运行时动态地获取类的信息并操纵类的对象。这种能力使得开发人员能够在编写程序时不确定具体类的情况下,依然能实现对类...

    C#动态加载DLL主要说明如何通过反射实现动态加载DLL

    在.NET框架中,C#程序员...通过以上解释,我们可以理解如何利用反射在C#中动态加载和执行DLL文件,以及在使用过程中需要注意的关键点。动态加载DLL是.NET开发中的一个重要技巧,它使得我们的应用程序更加灵活和可扩展。

    C#动态加载程序集

    在这个示例中,我们首先加载了DynamicAssembly.dll程序集,然后获得了程序集里的所有类,接着找到实现了IPersonControl接口的类,创建了类的实例,并调用了类的方法。 动态加载程序集是C#中的一种重要机制,可以...

    C#实现反射调用动态加载的DLL文件中的方法

    ### C#中使用反射调用动态加载的DLL文件中的...通过以上步骤,我们不仅实现了反射的基本原理,还展示了如何利用反射技术动态地加载和调用DLL文件中的方法,这对于开发过程中需要灵活配置或扩展功能的应用来说非常有用。

    Java反射动态加载实例类

    通过本示例,我们不仅理解了Java反射的基本概念和用途,还学会了如何利用反射动态加载并操作实例类。反射提供了一种灵活的方式来处理类和对象,尤其是在编写框架和插件系统时,能够根据运行时的条件动态地加载和执行...

    反射,动态加载指定类调用类中的方法

    在“反射,动态加载指定类调用类中的方法”这个主题中,我们将深入探讨如何使用反射来实现动态加载和执行类的方法。首先,我们需要理解几个关键的反射API: 1. `Class&lt;?&gt;`: 这是所有Java类的通用表示,通过`Class....

    利用反射,动态加载DLL,卸载DLL

    本篇将深入探讨如何利用反射动态加载和卸载DLL,以及在实际应用中的场景。 首先,我们需要了解DLL(动态链接库)在Windows操作系统中的作用。DLL文件是一组可重用的函数和数据,多个应用程序可以共享它们,以减少...

    利用反射动态加载dll

    在本例中,我们将讨论如何利用反射动态加载DLL文件,并结合SQL Server数据库来实现这一功能。 首先,我们需要理解动态加载DLL的基本概念。在传统的编程模式中,DLL(动态链接库)是在编译时静态链接到应用程序中的...

    基于WPF开发的插件式DLL动态加载源码,使用反射方式实现,可以直接当作模板使用.zip

    本资源是一个关于如何在WPF应用中实现插件式DLL动态加载的示例,使用了反射这一强大的特性。 首先,让我们了解什么是插件架构。插件架构是一种软件设计模式,允许主应用程序在运行时动态地发现和加载外部组件,即...

    Java技术----实现JAVA的动态类载入机制

    在Java编程语言中,动态类加载机制是一种强大...通过自定义类加载器和利用反射API,我们可以实现更高级的功能,比如动态加载和执行类,或者在运行时修改对象的行为。这使得Java成为一个高度适应性和可扩展的编程语言。

    学习python第十一天 反射、动态加载模块.pdf

    Python反射机制和动态加载模块...Python的反射机制和动态加载模块功能对于开发者来说非常有价值,它们可以让程序更加灵活和可扩展。但是,需要注意的是,反射机制的使用需要遵守一定的规则和约定,以免出现混乱和错误。

    利用反射 实现一个自制的struts

    反射在Java中是一个强大的工具,它允许程序在运行时检查和操作类、接口、字段和方法的信息,甚至可以动态调用方法。 首先,我们需要理解反射的基本概念。在Java中,`java.lang.Class`类和`java.lang.reflect`包提供...

    动态加载jar包

    动态加载jar包是一种在程序运行时按需引入外部库或者组件的...通过自定义类加载器和反射机制,我们可以实现在运行时加载新的功能,或者根据环境动态调整应用的行为,这对于大型、复杂系统的开发和维护具有重要意义。

    C# 反射实例代码 接口方式动态加载dll方式Reflection

    本实例代码主要探讨如何通过接口方式利用反射来动态加载DLL文件,这对于模块化开发和插件式架构非常有用。下面将详细介绍这个过程及其相关知识点。 首先,我们需要理解什么是接口。接口(Interface)在C#中是一种...

    C# 反射实例代码 接口方式动态加载dll方式

    通过这种方式,我们可以利用反射和接口实现动态加载和调用DLL中的功能,使得程序具有更好的可扩展性,可以灵活地集成新的功能模块而无需修改原始代码。 在实际应用中,这种技术常用于插件系统、框架设计、跨程序集...

    利用反射和动态代理机制实现自定义拦截器Interceptor

    利用反射和动态代理机制实现自定义拦截器Interceptor 在本文中,我们将探讨如何利用反射和动态代理机制来实现自定义拦截器Interceptor。拦截器Interceptor是一种常见的设计模式,用于在方法调用前后执行某些操作,...

    动态加载类机制JAVA

    5. 引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和应用程序类加载器(AppClassLoader): - 这是JVM内置的三种类加载器,它们分别负责加载JDK的核心类库、JRE的扩展类库以及用户...

    反射机制和类加载机制学习总结

    3. **应用程序类加载器(Application ClassLoader)**:负责加载用户路径(classpath)指定的类。 #### 八、类加载机制的优点 1. **安全性**:通过验证阶段确保类文件的安全性。 2. **性能优化**:类加载器可以...

    Java代码执行漏洞中类动态加载的应用1

    本文主要探讨了Java代码执行漏洞中类动态加载的应用,特别是通过自定义ClassLoader和反射调用`defineClass`方法来实现字节码的动态解析。 首先,Java中类的加载方式有两种:显式加载和隐式加载。隐式加载通常发生在...

Global site tag (gtag.js) - Google Analytics