Jay*_* Ch 2 java reflection spring javassist lombok
在一个项目中,我正在尝试javassist(java 二进制代码操作库)。
我能够使用下面的代码创建一个简单的 POJO 类
public static Class<?> createClass(ModelClass clazz) throws NotFoundException, CannotCompileException {
ModelProperty[] properties = clazz.getProperties();
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass(clazz.getName());
// add annotation
ClassFile classFile = ctClass.getClassFile();
ConstPool constpool = classFile.getConstPool();
AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constpool, AnnotationsAttribute.visibleTag);
System.out.println(Data.class.getName());
Annotation annotation = new Annotation(lombok.Data.class.getName(), constpool);
Annotation annotation1 = new Annotation(Component.class.getName(), constpool);
Annotation annotation2 = new Annotation(Deprecated.class.getName(), constpool);
annotationsAttribute.setAnnotations(new Annotation[] {annotation, annotation1, annotation2});
ctClass.getClassFile().addAttribute(annotationsAttribute);
for (ModelProperty property : properties) {
String camelCaseField = property.getName().substring(0, 1).toUpperCase() + property.getName().substring(1);
CtField ctField = new CtField(resolveCtClass(property.getType()), property.getName(), ctClass);
ctClass.addField(ctField);
// add getter
// CtMethod fieldGetter = CtNewMethod.getter("get" + camelCaseField, ctField);
// ctClass.addMethod(fieldGetter);
// add setter
// CtMethod fieldSetter = CtNewMethod.setter("set" + camelCaseField, ctField);
// ctClass.addMethod(fieldSetter);
}
return ctClass.toClass();
}
// ModelClass
@Data
public class ModelClass {
private String name;
private ModelProperty[] properties;
public void setName(String name) {
this.name = name;
}
public void setModelProperty(ModelProperty[] properties) {
this.properties = properties;
}
}
// ModelProperty
@Data
public class ModelProperty {
private String name;
private Class<?> type;
public void setType(String type) {
switch (type.toLowerCase()) {
case "int":
case "integer":
this.type = Integer.class;
break;
case "float":
this.type = Float.class;
break;
case "str":
case "string":
this.type = String.class;
break;
case "bool":
case "boolean":
this.type = Boolean.class;
break;
default:
this.type = String.class;
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我能够使用createClass方法创建类。在使用 Reflection API 检查类时,我注意到lombok.Data注释没有添加到类中。
Class<?> clazz = PojoCreator.createClass(modelClassPerson);
for (final Method method : clazz.getMethods()) {
System.out.println(method);
}
for (final Annotation annotation : clazz.getAnnotations()) {
System.out.println(annotation);
}
for (final Method method : clazz.getDeclaredMethods()) {
System.out.println(method);
}
for (final Annotation annotation : clazz.getDeclaredAnnotations()) {
System.out.println(annotation);
}
Run Code Online (Sandbox Code Playgroud)
输出
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
@org.springframework.stereotype.Component(value="")
@java.lang.Deprecated(forRemoval=false, since="")
@org.springframework.stereotype.Component(value="")
@java.lang.Deprecated(forRemoval=false, since="")
Run Code Online (Sandbox Code Playgroud)
从输出中可以看到spring.Component和javalang.Deprecated已添加,但lombok.Data没有添加。
pom.xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<!-- <scope>annotationProcessor</scope> -->
</dependency>
Run Code Online (Sandbox Code Playgroud)
尝试将范围设置为compile、runtime、provided ,但似乎都不起作用。
使用mvn spring-boot:run在命令行中执行
我哪里做错了?
谢谢。
您不能在运行时使用lombok,您需要自己生成样板代码。
这是行不通的,因为 lombok 使用注释处理器(参见这个和那个)。
这意味着lombok程序运行时。已编译。
当您尝试在运行时插入注释时,lombok 注释将不会被处理,也不会生成任何内容。
如果您查看 lombok 注释的 javadoc,例如@Data
,您可以看到以下内容:
@Retention(来源)
这意味着注释在编译时可见,但它并不存在于字节码中,并且您也无法在运行时访问它。