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
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); }
3.3演示javassist实现接口60comm.powernode.bank.daoAccountDaopackage 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(); }
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.javassistJavassistTestpackage 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.daoAccountdaopackage 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>