提高反射效率可利用缓存来搞,另一种方法是,生成动态类的方式可直接调用方法,性能跟直接调一样,可代替反射;
做平台,大量使用反射或者动态生成类,泛型,等特性,会极大地提高平台通用行,不仅节省众多代码,灵活性高,提高性能,代码看起来也是非常的优雅;
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