标签:
提高反射效率可利用缓存来搞,另一种方法是,生成动态类的方式可直接调用方法,性能跟直接调一样,可代替反射;
做平台,大量使用反射或者动态生成类,泛型,等特性,会极大地提高平台通用行,不仅节省众多代码,灵活性高,提高性能,代码看起来也是非常的优雅;
1,首先我们需要定义个抽象类,为什么要定义抽象类呢,因为我们需要直接通过它去调用目标对象的和函数,所以要明确定义出来还引用嘛
public abstract class MethodInvoker { public abstract Object invoke(Object instance, String method,Object[] params); }2,然后我们顶一个工厂,用于创建代理MethodInvoker类
public class InvokerFactory { public static MethodInvoker createInvoker(Class clazz) throws Exception{ Method[] methods = clazz.getDeclaredMethods(); String className = clazz.getName(); // 创建类 ClassPool pool = ClassPool.getDefault(); CtClass methodInvoker = pool.makeClass("test.MethodInvokerImpl",pool.getCtClass("test.MethodInvoker")); String methodString = "public Object invoke(Object instance, String method,Object[] params) \n" + "{\n" + " if(method==null||method==\"\") \n" + " return null;\n" ; //关键在这里 for(int i=0;i<methods.length;i++){ Method method = methods[i]; Class returnType = method.getReturnType(); String methodName = method.getName(); int paramCount = method.getParameterCount(); Class[] parameterTypes = method.getParameterTypes(); methodString = methodString + " if(method.equals(\""+methodName+"\")) \n"; if(returnType.getName().equals("void")){ methodString = methodString + " { \n"; methodString = methodString + " (("+className+")instance)."+methodName+"("; } else methodString = methodString + " return (("+className+")instance)."+methodName+"("; for(int j=0;j<paramCount;j++){ Class cls = parameterTypes[j]; methodString = methodString +"("+cls.getName()+")params["+j+"]"; if((j+1)<paramCount) methodString = methodString +","; } methodString = methodString +"); \n"; if(returnType.getName().equals("void")){ methodString = methodString + " return null; \n"; methodString = methodString + " } \n"; } } methodString = methodString + " return null; \n" + "}\n"; // 添加一个方法 methodInvoker.addMethod(CtNewMethod.make(methodString, methodInvoker)); // 打印创建类的类名 Object instance = methodInvoker.toClass().newInstance(); MethodInvoker invoker = (MethodInvoker)instance; return invoker; } }
解释一下,这里面其实就是通过反射,分析目标类所有的方法,参数类型,参数个数,返回值类型,从而好根据传入的字符串匹配,一旦匹配到了就直接调用那个方法
例如,对于User这个类来说,会生成一个这样的动态方法出来
public Object invoke(Object instance, String method,Object[] params) { if(method==null||method=="") return null; if(method.equals("setUsername")) { ((test.User)instance).setUsername((java.lang.String)params[0]); return null; } if(method.equals("getUsername")) return ((test.User)instance).getUsername(); if(method.equals("getPassword")) return ((test.User)instance).getPassword(); if(method.equals("setPassword")) { ((test.User)instance).setPassword((java.lang.String)params[0]); return null; } return null; }
我的意思已经一目了然了吧,ok,我们实际上就是用javassist来生成类和方法的,这个类继承了MethodInvoker抽象类,实现了它的invoke方法;那么接下来,我们就很好办了,只需要根据我们生成的类实例化一个对象,然后强制转换成MethodInvoker引用,就可以调用了;
//采用生成动态类,达到直接调用函数的目的 public static void main(String[] args) throws Exception { User user = new User(); MethodInvoker invoker = InvokerFactory.createInvoker(user.getClass()); Object[] array = {"xingzai"}; invoker.invoke(user, "setUsername",array ); }是不是很方便呢;注意,这个invoke方法,如果你调用的函数有返回值,就return,没返回值就返回null;然后传入的参数按顺序构造一个参数数组,目前我这个例子还不支持数组参数和数组返回,大家可以改进一下,无非在生成invoke函数时,多注意判断一些特殊情况哈;
然后,建议大家最好在MethodFactory里,增加一个池化对象map;因为生成这个methodInvoker也是需要耗费时间的,这玩意可以通用,因此还是保存起来好一些,才能真正意义上提升性能
我做了一个性能测试
直接调:动态生成调:反射 = 1:1:30
标签:
原文地址:http://my.oschina.net/glarystar/blog/483657