美文网首页
Javassist创建POJO类

Javassist创建POJO类

作者: onmeiei | 来源:发表于2022-10-16 17:56 被阅读0次

Javassist创建POJO类,需要关注两个地方,第一个是Getter和Setter方法的构建:
javassist.CtNewMethod#setter,示例:

CtClass typeClass = classes.get(fieldType.getType());
CtField ctField = new CtField(typeClass, fieldName, ctClass);
ctField.setModifiers(Modifier.PRIVATE);

String camelFieldName = fieldName.toUpperCase().charAt(0) + fieldName.substring(1);

CtMethod setter = CtNewMethod.setter("set" + camelFieldName, ctField);
CtMethod getter = CtNewMethod.getter("get" + camelFieldName, ctField);

ctClass.addField(ctField);
ctClass.addMethod(setter);
ctClass.addMethod(getter);

第二个地方就是,如果是容器类(例如:List、Map)时,它的genericSignature的获取。

如果不设置GenericSignature,将反射将无法获取genericType,会影响反序列化(例如:json、mybatis、jdbctemplate等等)。

设置GenericSignature使用:javassist.CtField#setGenericSignature
示例:

String sig = "Ljava/util/List<Ljava/lang/String;>;";

CtClass ctClass = classPool.makeClass("flow.A");

CtClass fileType = classPool.get("java.util.List");
CtField ctField = new CtField(fileType, "name", ctClass);
ctField.setGenericSignature(sig);
ctField.setModifiers(Modifier.PRIVATE);

ctClass.addField(ctField);

可以看到GenericSignatureLjava/util/List<Ljava/lang/String;>;是一个有特殊规则的字符串,接下来就需要构建GenericSignature。

构建GenericSignature,主要使用:javassist.bytecode.SignatureAttribute.ObjectType#encode
示例:

class Sample {
    private final Set<String> basicTypes;
    private final Set<String> collectionTypes;

    public BeanDefines() {
        basicTypes = Set.of("String", "Boolean", "Integer", "Double");
        collectionTypes = Set.of("List", "Map");
    }

    public void addField(CtClass ctClass, FieldType fieldType) {
          final ClassPool classPool = ClassPool.getDefault();
          
          try {
            CtClass typeClass = classPool.makeClass(fieldType.getType(), baseBean);
            CtField ctField = new CtField(typeClass, fieldName, ctClass);
            ClassType genericSignature = computeClassType(fieldType);
            ctField.setGenericSignature(genericSignature.encode());
            ctField.setModifiers(Modifier.PRIVATE);

            String camelFieldName = fieldName.toUpperCase().charAt(0) + fieldName.substring(1);

            CtMethod setter = CtNewMethod.setter("set" + camelFieldName, ctField);
            CtMethod getter = CtNewMethod.getter("get" + camelFieldName, ctField);

            ctClass.addField(ctField);
            ctClass.addMethod(setter);
            ctClass.addMethod(getter);
        } catch (CannotCompileException e) {
            throw new IllegalArgumentException("Failed to create field(%s) of bean(%s)".formatted(fieldName, beanName), e);
        }
    }

    private ClassType computeClassType(FieldType fieldType) {
        String type = fieldType.getType();
        if (this.basicTypes.contains(type)) {
            return new ClassType("java.lang." + type);
        }

        if (this.collectionTypes.contains(type)) {
            List<FieldType> parameters = fieldType.getParameters();
            List<TypeArgument> types = new ArrayList<>();
            for (FieldType parameter : parameters) {
                types.add(new TypeArgument(computeClassType(parameter)));
            }
            return new ClassType("java.util." + type, types.toArray(new TypeArgument[0]));
        }

        return new ClassType(baseClass.getPackageName() + "." + type);
    }

    private static class FieldType {
        private String type;
        private List<FieldType> parameters;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public List<FieldType> getParameters() {
            return parameters;
        }

        public void setParameters(List<FieldType> parameters) {
            this.parameters = parameters;
        }

        @Override
        public String toString() {
            return "FieldType{" +
                    "type='" + type + '\'' +
                    ", parameters=" + parameters +
                    '}';
        }
    }
}

相关文章

网友评论

      本文标题:Javassist创建POJO类

      本文链接:https://www.haomeiwen.com/subject/wvsdzrtx.html