生成动态类代替反射

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

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

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

时间: 2025-01-17 16:10:36

生成动态类代替反射的相关文章

Dubbo使用javassist生成动态类

Dubbo使用javassist生成动态类 在服务(本地和远程)暴露的时候会调用proxyFactory.getInvoker方法 具体位置: 本地暴露:ServiceConfig#exportLocal line:538 远程暴露: ServiceConfig#doExportUrlsFor1Protocol line:512 会先调用AOP织入的类StubProxyFactoryWrapper#getInvoker 然后执行JavassistProxyFactory#getInvoker J

JSP-讲解(生成java类、静态导入与动态导入)

一.JSP技术简介 JSP是Java Server Page的缩写,它是Servlet的扩展,它的作用是简化网站的创建和维护. JSP是HTML代码与Java代码的混合体. JSP文件通常以JSP或JSPX的扩展名. JSP拥有自己的语法. JSP形式上像HTML,但本质上是Servlet. JSP的出现,使得将Web开发中的HTML与业务逻辑代码有效分离成为可能.通常JSP只负责生成动态的HTML文档,而业务逻辑由其他Java组件如JavaBean来实现.JSP可以通过Scriptlet来访问

Java中动态代理技术生成的类与原始类的区别 (转)

用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后来定义的逻辑.这样就达到了动态的在原有类上增加一些功能.比如日志打印,拦截信息等. 这里只关心动态代理技术生成新的类,先不管虚拟机是如何去生成类,用了什么字节码生成技术,怎么产生字节码等这一系列动作.现在只关心最后生成的新类长什么样,它和老类有什么区别.为了获取到生成后的代理类的字节码并且反编译成我

动态生成实体类

转载: .net 根据匿名类生成实体类,根据datatable生成实体类,根据sql生成实体类 在开发中可能会遇到这几种情况 1.EF或LINQ查询出来的匿名对象在其它地方调用不方便,又懒的手动建实体类 2.通过datatable反射实体需要先建一个类 ,头痛 3.通过SQL语句返回的实体也需要先建一个类 ,头痛 4.如果通过代码生成器要写模版,需要安装或者不想生成一堆不用的类 为了解决上面的不便之处,我封装了一个实体生成类,可以扔到程序里面任意调用 封装类: using System; usi

JDK和CGLIB生成动态代理类的区别

 关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代理:程序员事先写好代理对象类,在程序发布前就已经存在了: 动态代理:应用程序发布后,通过动态创建代理对象. 其中动态代理又可分为:JDK动态代理和CGLIB代理. 1.JDK动态代理 此时代理对象和目标对象实现了相同的接口,目标对象作为代理对象的一个属性,具体接口实现中,可以在调用目标对象相应方法前

JDK动态代理,动态生成代理类。

1.动态代理涉及到的类 (1) Java.lang.reflect.Proxy类,作用:动态生成代理类和对象 (2) Java.lang.reflect.InvocationHandler(处理器接口) 可以通过invoke方法实现对真实角色的代理访问,每次通过Proxy生成代理类对象时都要指定处理器对象. package com.xvl.proxy; /** * 接口:明星接口 * @author 1 * */ public interface Star { //面谈 void confer(

Python 实现接口类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)

实现接口类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethod class BaseMessage(metaclass=ABCMeta): @abstractmethod def send(self,subject,body,to,name): pass 方式二 class BaseMessage(object): def send(self, subject, body, to, name): raise NotImp

通过getAdaptiveExtension生成的动态类

通过getAdaptiveExtension生成的动态类 方便调式使用 请放在根目录下 原文地址:https://www.cnblogs.com/qiaozhuangshi/p/11007105.html

如何通过java反射将数据库表生成实体类?

首先有几点声明: 1.代码是在别人的基础进行改写的: 2.大家有什么改进的意见可以告诉我,也可以自己改好共享给其他人: 3.刚刚毕业,水平有限,肯定有许多不足之处: 4.希望刚刚学习java的同学能有所启发. //这个是做转换的类,里面的DB只是封装了数据库的连接,大家可以用自己的,随意 package com.tt.util.gen.entity.tool; import java.io.File;import java.io.FileWriter;import java.io.IOExcep