利用反射技术和读配置文件的方式实现动态加载类和执行函数
不改变主程序的代码,通过修改配置文件来控制程序的执行,使程序的执行更加灵活。其中properties配置文件的读取写入是根据哈希表执行的,而在现实生活中常常需要顺序读写配置文件,因此需要覆写Properties类,使其顺序读写配置文件。覆写Properties类,顺序读写配置文件
package exercise;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set;
/**
* 用于指定properites文件的存储顺序和输入顺序一样,使得顺序不发生改变
* OrderedProperties
*/
public class OrderedProperties extends Properties {
private static final long serialVersionUID = -4627607243846121965L;
private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();
public Enumeration<Object> keys() {
return Collections.<Object> enumeration(keys);
}
public Object put(Object key, Object value) {
keys.add(key);
return super.put(key, value);
}
public synchronized Object remove(Object key) {
keys.remove(key);
return super.remove(key);
}
public Set<Object> keySet() {
return keys;
}
public Set<String> stringPropertyNames() {
Set<String> set = new LinkedHashSet<String>();
for (Object key : this.keys) {
set.add((String) key);
}
return set;
}
}
测试代码
package exercise;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.Properties;
public class TestDemo {
public static void main(String[] args) {
Class<?> c1 = null ;
String strClassName="";
String strMethodName="";
//Scanner sc = new Scanner(System.in);
//strClassName = sc.next();
Properties pro = new OrderedProperties();
File f = new File("Person.properties");
try {
String strArgs[]; //存放参数值(字符串)
String strArgsType[]= {};//存放参数类型(字符串)
Class[] oArgsType=null; //存放参数类型对应的class对象
Object[] oArgs=null; //存放参数值对应的object对象
Object obj = null;
String flag="0";//方法开始标记
pro.load(new FileInputStream(f));
Iterator<String> it=pro.stringPropertyNames().iterator();//将properties文件中的所有键存放在迭代器中
while(it.hasNext()){ //判断key的类型并取出相应的值存放在相应变量中
String key=it.next();
if(key.equals("class"))
{
strClassName =pro.getProperty(key);
c1 = Class.forName(strClassName) ;
obj = c1.getConstructor().newInstance();
}
if(key.substring(0, 1).equals("f"))
{
flag = pro.getProperty(key);
}
if(key.subSequence(0, 1).equals("m"))
{
strMethodName = pro.getProperty(key);
}
if(key.substring(0, 1).equals("k"))
{
strArgsType= pro.getProperty(key).split(","); //通过,拆分参数类型(字符串)并保存在数组中
oArgsType = new Class[strArgsType.length];
for (int i = 0; i < strArgsType.length; i++) { //将所有类型字符串分别转换成Class对象
oArgsType[i] = getPrimitiveClass(strArgsType[i]);
// System.out.println(oArgsType[i].getName());
}
}
if(key.substring(0, 1).equals("v"))
{
strArgs= pro.getProperty(key).split(",");//通过,拆分参数值(字符串)并保存在数组中
oArgs = new Object[strArgs.length];
for (int i = 0; i < strArgs.length; i++) { //将所有参数值字符串分别转换成相应的数据类型并转成object对象
oArgs[i] = transferArguments(strArgsType[i], strArgs[i]);
// System.out.println(oArgs[i]);
}
}
if(key.substring(0, 1).equals("e")) //判断方法是否结束
{
Method met;
if(flag.equals("1"))
{
if(oArgsType!=null)//若方法中参数不为空则反射调用有参函数
{
met= c1.getMethod(strMethodName, oArgsType);
met.invoke(obj, oArgs);
oArgsType = null;
oArgs = null;
}
else //否则,反射调用无参函数
{
met = c1.getMethod(strMethodName);
met.invoke(obj);
}
}
}
}
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
private static Object transferArguments(String type, String value) {//将数据类型字符串转成相应的值(invoke方法中要接收参数值)
type = type.toLowerCase();
switch (type) {
case "int":
return Integer.valueOf(value);
case "double":
return Double.valueOf(value);
case "float":
return Float.valueOf(value);
case "char":
return (char)value.getBytes()[0];
case "string":
return value;
default:
System.out.println("undefined!");
return null;
}
}
private static Class getPrimitiveClass(String str) {//将数据类型转换成相应的class对象(getmethod方法中参数需要接收class对象)
str = str.toLowerCase();
switch (str) {
case "int":
return int.class;
case "double":
return double.class;
case "float":
return float.class;
case "char":
return char.class;
case "string":
return String.class;
default:
System.out.println("undefined!");
return Object.class;
}
}
}
测试类Person(测试类可根据需求写):
package exercise;
public class Person {
public void sayHello(String name,int age) {//有参方法
System.out.println("Hello "+ ",I'm"+name+", "+age);
}
public void print() {//无参方法
System.out.println("This is print function");
}
}
Person类的properties文件(Properties文件可以自己写,也可以通过程序生成,这里就自己写了):
s1=1
class=exercise.Person ##class类包路径
f1=1 ##f标记方法开始
m1=sayHello ##m方法名
k1=String,int ##k参数类型
v1=Lily,18 ##v参数值
e1=1 ##e标记方法结束
f2=1
m2=print
e2=1