码迷,mamicode.com
首页 > 其他好文 > 详细

生成动态类代替反射

时间:2015-07-25 13:55:49      阅读:121      评论:0      收藏:0      [点我收藏+]

标签:

提高反射效率可利用缓存来搞,另一种方法是,生成动态类的方式可直接调用方法,性能跟直接调一样,可代替反射;

做平台,大量使用反射或者动态生成类,泛型,等特性,会极大地提高平台通用行,不仅节省众多代码,灵活性高,提高性能,代码看起来也是非常的优雅;

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!