bytecode操作
来源:互联网 发布:乐视网络电视下载安卓 编辑:程序博客网 时间:2024/06/10 13:07
问题: 调用一个方法传入List of Object 然后根据配置文件去调用Object中的get方法,可是我只有一个List of Map。 map的key 就是get方法所需要调用的 比如map中有name 那个方法要调用的是getName
问题分析: 为了解决问题可有两个途径 1 就是老老实实的将map转化为一个javabean,那么就需要写多个javabean ,实现比较简单,工作量较大。2 修改需要此list的方法,让他能够读取map。
问题解决: 因为所要调用的工具设计的合理,很容易的扩充了原来的功能,专门做了一个读取map的datasource,用几行代码轻松解决。
问题深入:如果调用的工具没有进行如此合理的设计,应该怎么做?
问题继续: 采用分析出来的第一种方法,那就是转化为javabean,避免大工作量就需要写一个代码生成器。
问题缺点:虽然工作量不是十分巨大,但是直接生成大量的代码,不方便日后维护。
期待结果:创建一个类,内部有一Map 成员变量,但是没有getXXX的方法,在调用这种方法时,直接进入某一方法返回map中内容。
问题突破口:记得jdk 1.5的动态代理,开始研究。
新问题出现:动态代理,虽然可以进行方法拦截,但是必须有方法接口,否则无法调用。
寻找出路: 向Michael询问,得到答案:bytecode如asm ,或者aop 如aspectJ
继续分析: aspectJ语法已经忘记,aop方式感觉不能实现。理由如下,aop需要寻找横切点,但是横切点不存在。
查看asm: 官方文档看的云里雾里,示例代码感觉冗长拖沓,除非对class文件格式了解深入,很难快速编写代码。
新的突破:bytecode工具大搜索,找到javassist。 javassist:jboss子项目之一。可以以asm之类直接字节码操作,也可以已源代码级别的操作。查看示例代码,清晰明了。决定采用它来尝试。
资源: http://www.csg.is.titech.ac.jp/~chiba/javassist/
http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial.html
http://zyl.javaeye.com/blog/53740
代码:
1 CallClass.java 需要传入list 并且调用list中元素getXXX方法的类
package com.jeaomachine;
import java.lang.reflect.Method;
import java.util.List;
public class CallClass {
public static void call(List list) {
try {
for (Object o : list) {
Method m = o.getClass().getMethod("getName", null);
System.out.println("getName:/t"
+ m.invoke(o, null));
m = o.getClass().getMethod("getGendar", null);
System.out.println("getGendar:/t"
+ m.invoke(o, null));
m = o.getClass().getMethod("getTime", null);
System.out.println("getTime:/t"
+ m.invoke(o, null));
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
2 MainCalling.java 主程序,修改字节码,调用CallClass
package com.jeaomachine;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
public class MainCalling {
public static void main(String[] args) {
try {
CtClass ctClass = ClassPool.getDefault().get(
"com.jeaomachine.VoClass");
List<String> strList = new ArrayList<String>();
strList.add("name");
strList.add("gendar");
strList.add("time");
for (int i = 0; i < strList.size(); i++) {
String name = (String) strList.get(i);
String name2 = "";
name2 = new String("" + name.charAt(0)).toUpperCase()
+ name.substring(1);
String mname = "public String get" + name2
+ "(){return (String)map.get(/"" + name + "/");}";
CtMethod mnew = CtNewMethod.make(mname, ctClass);
ctClass.addMethod(mnew);
}
ctClass.toClass();
VoClass a = new VoClass();
List<VoClass> list = new ArrayList<VoClass>();
Map<String, String> map = new HashMap<String, String>();
map.put("name", "the name");
map.put("gendar", "the gendar");
map.put("time", "the time");
a.setMap(map);
list.add(a);
map = new HashMap<String, String>();
map.put("name", "the name 2");
a = new VoClass();
a.setMap(map);
list.add(a);
CallClass.call(list);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
3 VoClass.java 存放Map的javaBean ,编写时没有getXXX 方法 但是期望被调用到
package com.jeaomachine;
import java.util.Map;
public class VoClass {
Map map=null;
public void setMap(Map map){
this.map=map;
}
// public String getName(){
// return "";
// }
}
代码分析: MainCalling 更改VoClass的字节码,根据map中的值(目前为hardcode)创建getXXX方法 将其加入list并且调用CallClass的call方法 此方法调用list中元素的getXXX方法。
至此调用不存在的方法的方法终于实现。
运行结果:
getName: the name
getGendar: the gendar
getTime: the time
getName: the name 2
getGendar: null
getTime: null
遇到障碍:使用过程中出现过classCast的异常,即将新的方法加入VoClass的类中时 强制转换newInstance出来的对象时出现。另外会出现重复的VoClass的异常。
解决方法:查看最新javassist版本为3.4 而我使用的是2.4 马上重新下载,编译,运行,一切正常。
- bytecode操作
- Java bytecode
- Java bytecode
- Java ByteCode
- java bytecode
- java bytecode
- 什么是Bytecode
- Java bytecode
- python ByteCode
- java bytecode
- Dalvik bytecode
- Java bytecode
- Java bytecode assembler : jasmin
- java bytecode security
- 一个python bytecode decompiler
- CGLIB - dynamic bytecode generation
- hibernate.bytecode.use_reflection_optimizer
- Codechef Bytecode 1-10
- js四舍五入
- Hibernate many-to-one的Lazy设置的问题
- URL传递中文参数乱码问题
- vector 和list
- getSession()与getHibernateTemplate()区别
- bytecode操作
- 开发自己的类加载器_文件系统类加载器
- Web编程是函数式编程
- mssql出错:A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations.
- 年终了,为这一年留下点东西吧
- filter-mapping顺序
- hibernate 批量操作
- 【转】GTY(())的内部
- WF-异常捕获与补偿的应用说明