使用javassist进行动态编程
今天在研究dubbo时,发现一个新的知识点,可以使用javassist包进行动态编程,hibernate也使用该包进行编程。晚上百度了很多资料,将它的特性以代码的形式展现出来。
package com.zhi.demo; import java.lang.reflect.Field; import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.Loader;
import javassist.Modifier;
import javassist.bytecode.AccessFlag; /**
* Javassist动态编程测试
*
* @date 2019年03月11日23:00:33
*
*/
public class JavassistTest {
public static void main(String[] args) {
try {
test();
} catch (Exception e) {
e.printStackTrace();
}
} private static void test() throws Exception {
System.out.println("-------------------新增类------------------");
ClassPool pool = ClassPool.getDefault();
// 创建类
CtClass ct = pool.makeClass("com.zhi.Person");
// 让类实现Cloneable接口
ct.setInterfaces(new CtClass[] { pool.makeInterface("java.lang.Cloneable") }); // 添加一个int类型的共有属性
CtField fieldId = new CtField(CtClass.intType, "id", ct);
fieldId.setModifiers(AccessFlag.PUBLIC);
ct.addField(fieldId); // 添加一个默认构造器
CtConstructor constructor1 = CtNewConstructor.make("public Person(){this.id=1;}", ct);
ct.addConstructor(constructor1); // 添加方法
CtMethod helloM = CtNewMethod
.make("public void hello(String des){System.out.println(\"执行hello方法,\"+des+\",我的id是\"+this.id);}", ct);
ct.addMethod(helloM); // 将生成的.class文件保存到磁盘
ct.writeFile(); // 加载目标类,可用ct.toClass()或new Loader(pool).loadClass()
Class<?> clazz = ct.toClass();
// Class<?> clazz = new Loader(pool).loadClass("com.zhi.Person"); // 输出类基本信息
System.out.println("包名:" + clazz.getPackageName());
System.out.println("类名:" + clazz.getName());
System.out.println("简要类名:" + clazz.getSimpleName());
System.out.println("限定符:" + Modifier.toString(clazz.getModifiers()));
System.out.println("继承类:" + clazz.getSuperclass().getName());
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("属性名称:" + field.getName() + ",属性类型:" + field.getType() + ",限定符:"
+ Modifier.toString(field.getModifiers()));
} // 构造一个对象,并执行hello方法
Object ob = clazz.getDeclaredConstructor().newInstance();
clazz.getMethod("hello", String.class).invoke(ob, "张三"); // 解冻(执行toClass后会自动冻结)
ct.defrost(); System.out.println("-------------------修改类------------------"); // 添加一个String类型的私有属性
CtField fieldName = new CtField(pool.get(String.class.getName()), "name", ct);
fieldName.setModifiers(AccessFlag.PRIVATE);
ct.addField(fieldName); // 添加带参的构造函数
CtConstructor constructor2 = new CtConstructor(new CtClass[] { pool.get(String.class.getName()) }, ct);
constructor2.setModifiers(Modifier.PUBLIC);
constructor2.setBody("{this.name=$1;}");
ct.addConstructor(constructor2); ct.addMethod(CtNewMethod.make("public void setName(String name){this.name=name;}", ct));
ct.addMethod(CtNewMethod.make("public String getName(){return this.name;}", ct)); ct.writeFile(); // 加载类,若前面已用ct.toClass()进行加载,则这里不能再用ct.toClass()加载,否则会出错,同一个加载不能2次加载同一个类
clazz = new Loader(pool).loadClass("com.zhi.Person"); fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("属性名称:" + field.getName() + ",属性类型:" + field.getType() + ",限定符:"
+ Modifier.toString(field.getModifiers()));
} ob = clazz.getDeclaredConstructor(String.class).newInstance("马云");
System.out.println("执行getName方法得到的值为:" + clazz.getMethod("getName").invoke(ob));
}
}
执行上面代码输出结果为:
-------------------新增类------------------
包名:com.zhi
类名:com.zhi.Person
简要类名:Person
限定符:public
继承类:java.lang.Object
属性名称:id,属性类型:int,限定符:public
执行hello方法,张三,我的id是1
-------------------修改类------------------
属性名称:id,属性类型:int,限定符:public
属性名称:name,属性类型:class java.lang.String,限定符:private
执行getName方法得到的值为:马云
说明:
$0,$1,$2:分别代表this,第一个参数,第二个参数
$r:方法返回值的类型。
$_:方法返回值
依赖包
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.24.1-GA</version>
</dependency>
使用javassist进行动态编程的更多相关文章
- Java动态编程初探——Javassist
最近需要通过配置生成代码,减少重复编码和维护成本.用到了一些动态的特性,和大家分享下心得. 我们常用到的动态特性主要是反射,在运行时查找对象属性.方法,修改作用域,通过方法名称调用方法等.在线的应用不 ...
- 【java编程-Javassist】秒懂Java动态编程(Javassist研究)
作者:ShuSheng007 来源:CSDN 原文:https://blog.csdn.net/ShuSheng0007/article/details/81269295 版权声明:本文为博主原创文章 ...
- Java安全之Javassist动态编程
Java安全之Javassist动态编程 0x00 前言 在调试CC2链前先来填补知识盲区,先来了解一下Javassist具体的作用.在CC2链会用到Javassist以及PriorityQueue来 ...
- Java动态编程---动态代理
java中动态编程用到的技术有:反射(动态代理),javassist和ASM,这几种动态编程方法相比较,在性能上Javassist高于反射,但低于ASM,因为Javassist增加了一层抽象.在实现成 ...
- java 动态代理 和动态编程
概述 代理分两种技术,一种是jdk代理(机制就是反射,只对接口操作),一种就是字节码操作技术.前者不能算技术,后者算是新的技术.未来将有大的动作或者较为广泛的应用和变革,它可以实现代码自我的编码(人工 ...
- [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程
[.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...
- 十七、C# 反射、特性和动态编程
反射.特性和动态编程 1.访问元数据 2.成员调用 3.泛型上的反射 4.自定义特性 5.特性构造器 6.具名参数 7.预定义特性 8.动态编程 特性(attribute)是在一个程序集中插入 ...
- [.NET] 《Effective C#》快速笔记 - C# 中的动态编程
<Effective C#>快速笔记 - C# 中的动态编程 静态类型和动态类型各有所长,静态类型能够让编译器帮你找出更多的错误,因为编译器能够在编译时进行大部分的检查工作.C# 是一种静 ...
- C# 4动态编程新特性与DLR剖析
=================================================== 注:很久没有发文了,贴一篇新文吧.从Word直接贴过来的,没仔细排版,诸位海涵.有关DLR和C# ...
随机推荐
- 在阿里云服务器上搭建xampp遇到的问题
参考文章:http://blog.csdn.net/hel12he/article/details/49781813 http://www.laozuo.org/8178.html http://bl ...
- R语言barplot双坐标作图
需要注意的是,设置其中的柱子的宽度,间隔的宽度.有公式如下 width为柱子的宽度 space为间隔宽度 barnumbers 为柱子数量 那么xlim的设置右侧范围为:(width + space) ...
- d3.select(this)不能用箭头函数
d3中典型的数据绑定片段 const items = svg.selectAll('g') .data(gdfs,(d)=> d.name); const enter = items.enter ...
- git分支错误提交导致代码丢失--窗口提示HEAD detached错误
今天开发时git 检出分支到本地时操作错误,导致在一个临时分支上开发,且把代码提交了,结果代码未提交到任何分支,提交时还报了个错: HEAD detached at 4d927fa4 后来把代码重新检 ...
- linux基础01-bash特性
(1) ls -l:长格式文件类型: -:普通文件 (f) d: 目录文件 b: 块设备文件 (block) c: 字符设备文件 (character) l: 符号链接文件(symbolic link ...
- linux网络常用命令
1,显示网桥 brctl show2,显示ip ip a3,查看openvswitch的配置信息 ovs-vsctl show4,显示网络命名空间 ip netns5,显示DHCP信息 ps -ef ...
- JavaScript 第一章总结
A quick dip into javascipt The way JavaScript works HTML 用一系列的 markup 来呈现整个 content 的 structure.CSS ...
- C# 测试代码段性能耗时
一: DateTime BeginTime = System.DateTime.Now; //代码 DateTime EndTi ...
- Hadoop/HBase Capacity Planning
http://blog.cloudera.com/blog/2010/08/hadoophbase-capacity-planning/
- Java -------- 首字母相关排序总结
Java 字符串数组首字母排序 字符串数组按首字母排序:(区分大小写) String[] strings = new String[]{"ba","aa",&q ...