博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[编织消息框架][JAVA核心技术]动态代理应用5-javassist
阅读量:4494 次
发布时间:2019-06-08

本文共 5786 字,大约阅读时间需要 19 分钟。

基础部份:

修改class我们用到javassist,在pom.xml添加

3.18.2-GA
org.javassist
javassist
${javassist.version}

 

1.ClassPool 负责加载CtClass,其中可添加ClassPath,优先级从父ClassPath加载

2.CtClass 处理class信息 从ClassPool make
3.CtField 处理field信息
4.CtMethod 处理method信息
5.CtConstructor 处理constructor信息

ClassPool 源码浅读:

AccessController.doPrivileged 方法能够使一段受信任代码获得更大的权限,甚至比调用它的应用程序还要多,可做到临时访问更多的资源,

由于技术内容跟本书无太大关系,我们只关心当抛出java.security.AccessControlException异常时,就考虑添加上去即可

 

实现部份:

1 public class TestJavassist { 2     public interface TestObject { 3     public void a(int a, String b); 4  5     public void setAge(int value); 6  7     public int getAge(); 8     } 9 10     public static void main(String[] args) throws Exception {11         String proxyClassName = TestObject.class.getCanonicalName() + "$$$$";12         ClassPool classPool = ClassPool.getDefault();13         CtClass ctClass = classPool.makeClass(proxyClassName);14 15         // 设置接口16         CtClass[] interfaces = new CtClass[1];17         interfaces[0] = classPool.get(TestObject.class.getName());18         ctClass.setInterfaces(interfaces);19 20         // 添加字段21         CtField ctField = new CtField(classPool.get(int.class.getName()), "age", ctClass);22         // 设置field属性23         ctField.setModifiers(Modifier.PRIVATE);24         ctClass.addField(ctField);25 26         // 添加 age getter'setter方法27         String setbody = "{this.age = $1;}";28         String getbody = "{return this.age;}";29         for (Method method : TestObject.class.getDeclaredMethods()) {30             String body = null;31             switch (method.getName()) {32                 case "setAge":33                     body = setbody;34                 break;35                 case "getAge":36                     body = getbody;37                 break;38                 case "a":39                     body = "{System.out.println($1);System.out.println($2);}";40                 break;41                 default:42                     continue;43             }44 45             Class
returnType = method.getReturnType();46 // 转换参数CtClass47 CtClass[] parameterCtClass = new CtClass[method.getParameterTypes().length];48 for (int i = 0; i < method.getParameterTypes().length; i++) {49 parameterCtClass[i] = classPool.get(method.getParameterTypes()[i].getName());50 }51 CtMethod ctMethod = new CtMethod(classPool.get(returnType.getName()), method.getName(), parameterCtClass, ctClass);52 ctMethod.setModifiers(method.getModifiers());53 ctMethod.setBody(body);54 ctClass.addMethod(ctMethod);55 56 }57 // 添加构造58 ctClass.addConstructor(CtNewConstructor.defaultConstructor(ctClass));59 60 Class
clz = ctClass.toClass();61 TestObject obj = (TestObject) clz.newInstance();62 obj.setAge(30);63 System.out.println("age : " + obj.getAge());64 obj.a(111, "bbb");65 66 // ctClass.writeFile("f:/test.class");67 }68 }

源码讲解

1.先通过classPool.makeClass 创建新的类,名称是原来类+自定义标记

2.所有的java类型必须转换成CtClass

3.要给创建的自定义类CtClass 添加接口类或继承父类,保留原类型

4.创建方法时特别注意处理java类型 

5.可添加构造方法

下面给出常用的参数对照表,注意:在不同域使用不同有的少点,不过都大同小异

 接着在之前的TestProxy 测试添加 testJavassist 看下执行效率,速度与native相差不大,原因是生成的指令很少,感兴趣的话通过 ctClass.writeFile()保存class 然后再用javap查看生成指令数

1 public static void testJavassist() throws Exception { 2     String proxyClassName = UserService.class.getCanonicalName() + "$$$$"; 3  4     ClassPool classPool = ClassPool.getDefault(); 5     CtClass ctClass = classPool.makeClass(proxyClassName); 6  7     // 设置接口 8     CtClass[] interfaces = new CtClass[1]; 9     interfaces[0] = classPool.get(UserService.class.getName());10     ctClass.setInterfaces(interfaces);11 12     // 添加 方法13     for (Method method : UserService.class.getDeclaredMethods()) {14         String body = null;15         switch (method.getName()) {16         case "getName":17             body = "{return $1 + \"\";}";18         break;19         case "getAge":20             body = "{return ($w)$1;}";21         break;22         default:23             continue;24         }25 26         Class
returnType = method.getReturnType();27 // 转换参数CtClass28 CtClass[] parameterCtClass = new CtClass[method.getParameterTypes().length];29 for (int i = 0; i < method.getParameterTypes().length; i++) {30 parameterCtClass[i] = classPool.get(method.getParameterTypes()[i].getName());31 }32 CtMethod ctMethod = new CtMethod(classPool.get(returnType.getName()), method.getName(), parameterCtClass, ctClass);33 ctMethod.setModifiers(method.getModifiers());34 ctMethod.setBody(body);35 ctClass.addMethod(ctMethod);36 37 }38 // 添加构造39 ctClass.addConstructor(CtNewConstructor.defaultConstructor(ctClass));40 Class
clz = ctClass.toClass();41 UserService proxy = (UserService) clz.newInstance();42 run("javassist", proxy);43 }

 

native: 177 native: 183 native: 128 native: 171 native: 127 native: 141 native: 184 native: 126 native: 127 native: 127 native: 127 native: 126 native: 127 native: 126 native: 127
jdk: 214 jdk: 169 jdk: 169 jdk: 169 jdk: 169 jdk: 169 jdk: 170 jdk: 169 jdk: 170 jdk: 169 jdk: 169 jdk: 171 jdk: 170 jdk: 169 jdk: 170
javassist: 146 javassist: 139 javassist: 140 javassist: 140 javassist: 140 javassist: 139 javassist: 140 javassist: 140 javassist: 138 javassist: 140 javassist: 140 javassist: 141 javassist: 139 javassist: 139 javassist: 139

 

资料来源 :http://jboss-javassist.github.io/javassist/tutorial/tutorial2.html#runtime

http://wsmajunfeng.iteye.com/blog/1912983

转载于:https://www.cnblogs.com/solq111/p/6672527.html

你可能感兴趣的文章
C语言指针
查看>>
Java的安装
查看>>
Docker 安装及问题处理
查看>>
document
查看>>
Hadoop下大矩阵乘法Version2
查看>>
iPhone内存溢出——黑白苹果
查看>>
Struts2学习笔记(十二) 类型转换(Type Conversion)(下)
查看>>
tcpdump学习
查看>>
局域网内传输文件速度慢
查看>>
Linux的核心版本(摘抄)
查看>>
CASE表达式
查看>>
zkw线段树
查看>>
作业1226
查看>>
mainline.js主线
查看>>
fseek()
查看>>
Python学习笔记——PyQt控件中文字居中显示
查看>>
JAVA环境下利用solrj二次开发SOlR搜索的环境部署常见错误
查看>>
Beta阶段敏捷冲刺前准备
查看>>
mini web框架-3-替换模板
查看>>
Siamese Network简介
查看>>