当前位置: 首页 > 图灵资讯 > 技术篇> javassist动态生成类

javassist动态生成类

来源:图灵教育
时间:2023-06-04 09:14:04

1.使⽤javassist⽣成类58

来⾃百度百科:Javassist是Javassist⼀Java字节码的类库由开源分析、编辑和创建。它是由东京组成的⼯业⼤ShigeruChiba(千叶滋)是由学习数学和计算机科学系的Shigeru创建的。它已经添加了⼊开源代码JBoss应该是开源代码⽤服务器项⽬,通过使⽤Javassist对字节码操作为Jboss实现动态”AOP"框架。

2.Javassist的使用⽤59

我们要使⽤javassist,⾸先要引⼊它的依赖

<dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.29.1-GA</version></dependency>

3.案例演示593.1注意高于jdk8版本的59

运⾏注:添加两个参数,否则会出现异常。

--add-opensjava.base/java.lang=ALL-UNNAMED

--add-opensjava.base/sun.net.util=ALL-UNNAMED

javassist动态生成类_javassist

3.2案例演示javassist生成类59代码comm.powernode.bank.dao.AccountdaoJavasstestest中的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);        // classs在内存中生成        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");        // insertt调用方法        insertMethod.invoke(obj);    }

javassist动态生成类_Test_02

3.3演示javassist实现接口60comm.powernode.bank.daoAccountDao

package com.powernode.bank.dao;//这是一个接口,看看javassist能否实现  60public interface AccountDao {    void delete();}

com中的代码.powernode.bank.dao.AccountdaoJavassistestest中的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();    }

javassist动态生成类_Test_03

3.4演示javassist动态实现接口类61代码.powernode.bank.dao.AccountdaoJavasstestesttest中的testenerateacountdaoimpl方法

///演示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中,加载到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-61com中的代码.powernode.javassistJavassistTest

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;///案例演示javassisttisttist  59public 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中,加载到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);        // classs在内存中生成        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");        // insertt调用方法        insertMethod.invoke(obj);    }}

com.powernode.bank.daoAccountdao

package com.powernode.bank.dao;//这是一个接口,看看javassist能否实现  60public 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依赖于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>