今天在研究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进行动态编程的更多相关文章

  1. Java动态编程初探——Javassist

    最近需要通过配置生成代码,减少重复编码和维护成本.用到了一些动态的特性,和大家分享下心得. 我们常用到的动态特性主要是反射,在运行时查找对象属性.方法,修改作用域,通过方法名称调用方法等.在线的应用不 ...

  2. 【java编程-Javassist】秒懂Java动态编程(Javassist研究)

    作者:ShuSheng007 来源:CSDN 原文:https://blog.csdn.net/ShuSheng0007/article/details/81269295 版权声明:本文为博主原创文章 ...

  3. Java安全之Javassist动态编程

    Java安全之Javassist动态编程 0x00 前言 在调试CC2链前先来填补知识盲区,先来了解一下Javassist具体的作用.在CC2链会用到Javassist以及PriorityQueue来 ...

  4. Java动态编程---动态代理

    java中动态编程用到的技术有:反射(动态代理),javassist和ASM,这几种动态编程方法相比较,在性能上Javassist高于反射,但低于ASM,因为Javassist增加了一层抽象.在实现成 ...

  5. java 动态代理 和动态编程

    概述 代理分两种技术,一种是jdk代理(机制就是反射,只对接口操作),一种就是字节码操作技术.前者不能算技术,后者算是新的技术.未来将有大的动作或者较为广泛的应用和变革,它可以实现代码自我的编码(人工 ...

  6. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  7. 十七、C# 反射、特性和动态编程

    反射.特性和动态编程   1.访问元数据 2.成员调用 3.泛型上的反射 4.自定义特性 5.特性构造器 6.具名参数 7.预定义特性 8.动态编程   特性(attribute)是在一个程序集中插入 ...

  8. [.NET] 《Effective C#》快速笔记 - C# 中的动态编程

    <Effective C#>快速笔记 - C# 中的动态编程 静态类型和动态类型各有所长,静态类型能够让编译器帮你找出更多的错误,因为编译器能够在编译时进行大部分的检查工作.C# 是一种静 ...

  9. C# 4动态编程新特性与DLR剖析

    =================================================== 注:很久没有发文了,贴一篇新文吧.从Word直接贴过来的,没仔细排版,诸位海涵.有关DLR和C# ...

随机推荐

  1. 【UOJ#196】【BZOJ4574】[Zjoi2016]线段树

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=4574 http://uoj.ac/problem/196 考虑数字随机并且值域够大,我们 ...

  2. Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树

    E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...

  3. Python 传递任意数量的实参

    在定义函数的时候如果你不知道该函数在使用的时候要接收多少的实参怎么办? 好在python提供了可以接收任意数量的实参的操作. # def sandwitch(*ingredents): # print ...

  4. JS异步函数 返回值

    1.  js 异步的几种情况 : 1.1 异步操作由浏览器内核的 webcore 来执行: onclick 由浏览器内核的 DOM Binding 模块来处理,当事件触发的时候,回调函数会立即添加到任 ...

  5. cocos2dx 3.x 集成protobuf

    vs2013+cocos2dx 3.13.1 这篇博文是集成Lua版本的protobuf,集成C++版本的过程也可参考. 主要参考博文地址<cocos2dx 3.x C++搭建protobuf环 ...

  6. Codeforces 1076 E - Vasya and a Tree

    E - Vasya and a Tree 思路: dfs动态维护关于深度树状数组 返回时将当前节点的所有操作删除就能保证每次访问这个节点时只进行过根节点到当前节点这条路径上的操作 代码: #pragm ...

  7. Jmeter 如何引入外部jar 包

    最近使用Jmeter 测试需要引入Jar包,之前也遇到过,用过两种方式,各有利弊,今天又接触了一种方式,挺好,在此做一总结. 方法一:测试计划 通过 Add directory or jar to c ...

  8. blast | diamond 输出结果选择和解析 | 比对

    之前的文章:构建NCBI本地BLAST数据库 (NR NT等) | blastx/diamond使用方法 | blast构建索引 | makeblastdb 本地运行blast时,需要指定out fo ...

  9. JSON和Serialize数据格式的对比

    1.相同点: 都是把其它数据类型转换为可传输的字符串 都是结构性数据 2.不同点: JSON比Serialize序列后的格式要简洁 Serialize序列化的数据格式保存数据原有类型 3.扩展 JSO ...

  10. Confluence 6 配置边栏链接

    选择图标来显示或者隐藏,页面(pages),博客页面(blogs),快捷键(shortcuts )或者导航选项(navigation options).例如,如果你希望i的这个公开主要用于博客用途,你 ...