文章目录
一、拼接methodCode
与上一篇类似,而难点关键在于获取到Dao接口中的所有方法包括方法名、返回值类型、返回值个数等等
拼接参数代码如下:
//获取接口中所有的方法
Method methods[] = AccountDao.class.getDeclaredMethods();
Arrays.stream(methods).forEach(method -> {
//method是接口中的方法
try {
//开始拼接methodCode
StringBuilder methodCode = new StringBuilder();
methodCode.append("public ");//追加修饰符列表
methodCode.append(method.getReturnType().getName());//返回值类型
methodCode.append(" ");//追加一个空格
methodCode.append(method.getName());//追加方法名
methodCode.append("(");//追加一个小括号
//拼接参数
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(\"hello delete!!\");");//追加一个小括号+代码
//根据返回值 动态添加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);
//难度最大的就是methodCode:接口中不同方法的返回值类型 方法名 以及参数
CtMethod ctMethod = CtMethod.make(methodCode.toString(),ctClass);
//将方法添加到类中
ctClass.addMethod(ctMethod);
} catch (Exception e) {
e.printStackTrace();
}
});
此时拼接好的运行结果如下(较LOW)
二、调用方法
其余操作与上篇一致,不赘述。
完整代码如下:
/**
* 使用javassist动态生成类并实现接口中的所有方法
*/
@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是接口中的方法
try {
//开始拼接methodCode
StringBuilder methodCode = new StringBuilder();
methodCode.append("public ");//追加修饰符列表
methodCode.append(method.getReturnType().getName());//返回值类型
methodCode.append(" ");//追加一个空格
methodCode.append(method.getName());//追加方法名
methodCode.append("(");//追加一个小括号
//拼接参数
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(\"hello delete!!\");");//追加一个小括号+代码
//根据返回值 动态添加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);
//难度最大的就是methodCode:接口中不同方法的返回值类型 方法名 以及参数
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.delete();
accountDao.update("111",11.0);
accountDao.selectByActno("bwy_1004");
}
运行结果: