字节码技术:解决mybatis返回对象新增变量问题-javassist
根据枚举类型进行数据统计,当枚举类型有改动时,统计输出也需要动态改动。这时数据相关的对象变量和方法都需要改动,很不方便、
通过字节码技术,在类加载时生成对象类型:
TestVo.java
//对象class中没有变量, 只有公共的getType\setType方法,对外提供便利的数据读取和设置方式。
public class TestVo {
// set方法供外部直观调用
public void setType(int type,int value){
String mname = "set_type_" + alarm_type;
try {
Method method = this.getClass().getMethod(mname,int.class);
if(method == null ){
return ;
}
method.invoke(this, value);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
//get方法
public int getType(int type){
try {
String mname = "get_type_" + type;
Method method = this.getClass().getMethod(mname); // 需要与枚举类方法对应
if(method == null ){
return 0 ;
}
Object invoke = method.invoke(this, null);
return Integer.valueOf(invoke.toString());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return 0 ;
}
}
//系统启动时,动态修改类资源字节码,添加变量、get\set方法,然后加载对象class。
//字节码对类的变量和方法进行处理
public static void init () {
try {
AlarmTypeEnum[] enums = AlarmTypeEnum.values() ;
ClassPool cp = ClassPool.getDefault();
//添加项目资源路径,要不然找不到类 javassist.NotFoundException:
cp.insertClassPath(new ClassClassPath(AA.class ));
//类加载器加载一次,反射重复加载了同一个类会报错,这里直接采用路径 ,使用 AlarmTrendStatisticsVo.class.getName() 已经被加载 ,toclass会报错
CtClass cc = cp.get("com.**.TestVo" );
CtField[] fields = cc.getDeclaredFields();
List<String > list = Arrays.stream(fields).map(CtField::getName).collect(Collectors.toList());
for(TypeEnum typeEnum: enums) {
int type = typeEnum.getCode();
String fieldName = "type_" + type;
if(!list.contains(fieldName)){
//添加一个int类型的共有属性
CtField fieldId = new CtField(CtClass.intType, fieldName, cc);
fieldId.setModifiers(AccessFlag.PUBLIC);
cc.addField(fieldId);
// 添加get方法
CtMethod get = CtNewMethod
.make("public int get"+ StringUtil.upperCase(fieldName) +"( ){ return "+fieldName+";}", cc);
cc.addMethod(get);
// 添加set方法
CtMethod set = CtNewMethod
.make("public void set"+ StringUtil.upperCase(fieldName) +"( int i ){ this."+fieldName +" = i ;}", cc);
cc.addMethod(set);
}
}
cc.toClass();
// 释放对象
cc.detach();
}catch ( Exception e){
e.printStackTrace();
}
}

浙公网安备 33010602011771号