1. 使⽤javassist⽣成类 58
来⾃百度百科:Javassist是⼀个开源的分析、编辑和创建Java字节码的类库。是由东京⼯业⼤学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的。它已加⼊了开放源代码JBoss 应⽤服务器项⽬,通过使⽤Javassist对字节码操作为JBoss实现动态"AOP"框架。
2. Javassist的使⽤ 59
我们要使⽤javassist,⾸先要引⼊它的依赖
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.1-GA</version>
</dependency>
3. 案例演示 59
3.1 注意高于jdk8版本的 59
运⾏要注意:加两个参数,要不然会有异常。
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/sun.net.util=ALL-UNNAMED
3.2 案例演示javassist生成类 59
代码在com.powernode.bank.dao.AccountDao
JavassistTest中的testGenerateFirstClass方法
//案例演示javassist生成类 59
@Test
public void testGenerateFirstClass() throws Exception{
// 获取类池,这个类池就是用来给我生成class的
ClassPool pool = ClassPool.getDefault();
// 制造类(需要告诉javassist,类名是啥)
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造方法
String methodCode = "public void insert(){System.out.println(123);}";
CtMethod ctMethod = CtMethod.make(methodCode, ctClass);
// 将方法添加到类中
ctClass.addMethod(ctMethod);
// 在内存中生成类class
ctClass.toClass();
// 类加载到JVM当中,返回AccountDaoImpl类的字节码
Class clazz = Class.forName("com.powernode.bank.dao.impl.AccountDaoImpl");
// 创建对象
Object obj = clazz.newInstance();
// 获取AccountDaoImpl中的insert方法
Method insertMethod = clazz.getDeclaredMethod("insert");
// 调用方法insert
insertMethod.invoke(obj);
}
3.3 演示javassist实现接口 60
com.powernode.bank.dao
AccountDao
package com.powernode.bank.dao;
//这是一个接口看看javassist能不能实现 60
public interface AccountDao {
void delete();
}
代码在com.powernode.bank.dao.AccountDao
JavassistTest中的testGenerateImpl方法
//演示javassist实现接口 60
@Test
public void testGenerateImpl() throws Exception{
// 获取类池
ClassPool pool = ClassPool.getDefault();
// 制造类
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造接口
CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");
// 添加接口到类中
ctClass.addInterface(ctInterface); // AccountDaoImpl implements AccountDao
// 实现接口中的方法
// 制造方法
CtMethod ctMethod = CtMethod.make("public void delete(){System.out.println(\"hello delete!\");}", ctClass);
// 将方法添加到类中
ctClass.addMethod(ctMethod);
// 在内存中生成类,同时将生成的类加载到JVM当中。
Class clazz = ctClass.toClass();
// 创建对象这里进行了强转为AccountDao类型了,所以创建出来的对象可以直接调方法了
AccountDao accountDao = (AccountDao)clazz.newInstance();
accountDao.delete();
}
3.4 演示javassist动态实现接口类 61
代码在com.powernode.bank.dao.AccountDao
JavassistTest中的testGenerateAccountDaoImpl方法
//演示javassist动态实现接口类 61
@Test
public void testGenerateAccountDaoImpl() throws Exception{
// 获取类池
ClassPool pool = ClassPool.getDefault();
// 制造类
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造接口
CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");
// 实现接口
ctClass.addInterface(ctInterface);
// 实现接口中所有的方法
// 获取接口中所有的方法
Method[] methods = AccountDao.class.getDeclaredMethods();
Arrays.stream(methods).forEach(method -> {
// method是接口中的抽象方法
// 把method抽象方法给实现了。
try {
// public void delete(){}
// public int update(String actno, Double balance){}
StringBuilder methodCode = new StringBuilder();
methodCode.append("public "); // 追加修饰符列表
methodCode.append(method.getReturnType().getName()); // 追加返回值类型
methodCode.append(" ");
methodCode.append(method.getName()); //追加方法名
methodCode.append("(");
// 拼接参数 String actno, Double balance
Class[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class parameterType = parameterTypes[i];
methodCode.append(parameterType.getName());
methodCode.append(" ");
methodCode.append("arg" + i);
if(i != parameterTypes.length - 1){
methodCode.append(",");
}
}
methodCode.append("){System.out.println(11111); ");
// 动态的添加return语句
String returnTypeSimpleName = method.getReturnType().getSimpleName();
if ("void".equals(returnTypeSimpleName)) {
}else if("int".equals(returnTypeSimpleName)){
methodCode.append("return 1;");
}else if("String".equals(returnTypeSimpleName)){
methodCode.append("return \"hello\";");
}
methodCode.append("}");
System.out.println(methodCode);
//给ctClass制造方法
CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
//将方法添加到类中
ctClass.addMethod(ctMethod);
} catch (Exception e) {
e.printStackTrace();
}
});
// 在内存中生成class,并且加载到JVM当中
Class clazz = ctClass.toClass();
// 创建对象
AccountDao accountDao = (AccountDao) clazz.newInstance();
// 调用方法
accountDao.insert("aaaaa");
accountDao.delete();
accountDao.update("aaaa", 1000.0);
accountDao.selectByActno("aaaa");
}
4. 代码 58-61
代码在com.powernode.javassist
JavassistTest
package com.powernode.javassist;
import com.powernode.bank.dao.AccountDao;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import org.junit.Test;
import java.lang.reflect.Method;
import java.util.Arrays;
//案例演示javassist 59
public class JavassistTest {
//演示javassist动态实现接口类 61
@Test
public void testGenerateAccountDaoImpl() throws Exception{
// 获取类池
ClassPool pool = ClassPool.getDefault();
// 制造类
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造接口
CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");
// 实现接口
ctClass.addInterface(ctInterface);
// 实现接口中所有的方法
// 获取接口中所有的方法
Method[] methods = AccountDao.class.getDeclaredMethods();
Arrays.stream(methods).forEach(method -> {
// method是接口中的抽象方法
// 把method抽象方法给实现了。
try {
// public void delete(){}
// public int update(String actno, Double balance){}
StringBuilder methodCode = new StringBuilder();
methodCode.append("public "); // 追加修饰符列表
methodCode.append(method.getReturnType().getName()); // 追加返回值类型
methodCode.append(" ");
methodCode.append(method.getName()); //追加方法名
methodCode.append("(");
// 拼接参数 String actno, Double balance
Class[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class parameterType = parameterTypes[i];
methodCode.append(parameterType.getName());
methodCode.append(" ");
methodCode.append("arg" + i);
if(i != parameterTypes.length - 1){
methodCode.append(",");
}
}
methodCode.append("){System.out.println(11111); ");
// 动态的添加return语句
String returnTypeSimpleName = method.getReturnType().getSimpleName();
if ("void".equals(returnTypeSimpleName)) {
}else if("int".equals(returnTypeSimpleName)){
methodCode.append("return 1;");
}else if("String".equals(returnTypeSimpleName)){
methodCode.append("return \"hello\";");
}
methodCode.append("}");
System.out.println(methodCode);
//给ctClass制造方法
CtMethod ctMethod = CtMethod.make(methodCode.toString(), ctClass);
//将方法添加到类中
ctClass.addMethod(ctMethod);
} catch (Exception e) {
e.printStackTrace();
}
});
// 在内存中生成class,并且加载到JVM当中
Class clazz = ctClass.toClass();
// 创建对象
AccountDao accountDao = (AccountDao) clazz.newInstance();
// 调用方法
accountDao.insert("aaaaa");
accountDao.delete();
accountDao.update("aaaa", 1000.0);
accountDao.selectByActno("aaaa");
}
//演示javassist实现接口 60
@Test
public void testGenerateImpl() throws Exception{
// 获取类池
ClassPool pool = ClassPool.getDefault();
// 制造类
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造接口
CtClass ctInterface = pool.makeInterface("com.powernode.bank.dao.AccountDao");
// 添加接口到类中
ctClass.addInterface(ctInterface); // AccountDaoImpl implements AccountDao
// 实现接口中的方法
// 制造方法
CtMethod ctMethod = CtMethod.make("public void delete(){System.out.println(\"hello delete!\");}", ctClass);
// 将方法添加到类中
ctClass.addMethod(ctMethod);
// 在内存中生成类,同时将生成的类加载到JVM当中。
Class clazz = ctClass.toClass();
// 创建对象这里进行了强转为AccountDao类型了,所以创建出来的对象可以直接调方法了
AccountDao accountDao = (AccountDao)clazz.newInstance();
accountDao.delete();
}
//案例演示javassist生成类 59
@Test
public void testGenerateFirstClass() throws Exception{
// 获取类池,这个类池就是用来给我生成class的
ClassPool pool = ClassPool.getDefault();
// 制造类(需要告诉javassist,类名是啥)
CtClass ctClass = pool.makeClass("com.powernode.bank.dao.impl.AccountDaoImpl");
// 制造方法
String methodCode = "public void insert(){System.out.println(123);}";
CtMethod ctMethod = CtMethod.make(methodCode, ctClass);
// 将方法添加到类中
ctClass.addMethod(ctMethod);
// 在内存中生成类class
ctClass.toClass();
// 类加载到JVM当中,返回AccountDaoImpl类的字节码
Class clazz = Class.forName("com.powernode.bank.dao.impl.AccountDaoImpl");
// 创建对象
Object obj = clazz.newInstance();
// 获取AccountDaoImpl中的insert方法
Method insertMethod = clazz.getDeclaredMethod("insert");
// 调用方法insert
insertMethod.invoke(obj);
}
}
com.powernode.bank.dao
接口AccountDao
package com.powernode.bank.dao;
//这是一个接口看看javassist能不能实现 60
public interface AccountDao {
void delete();
int insert(String actno);
int update(String actno, Double balance);
String selectByActno(String actno);
}
配置文件pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.powernode</groupId>
<artifactId>course11</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<!--javassist依赖-->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.1-GA</version>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<!-- 编译代码使用的jdk版本-->
<maven.compiler.source>1.8</maven.compiler.source>
<!-- 运行程序使用的jdk版本-->
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
标签:methodCode,生成,powernode,ctClass,动态,com,append,javassist
From: https://blog.51cto.com/u_15784725/6407826