是否可以用注释猴子修补 scala final class?
Is it possible to monkey patch a scala final class with an annotation?
我使用 Scala 作为我的语言。我使用 Google Objectify 作为我的持久性 API 将对象存储到 Google App Engine 的数据存储中。任何要通过 Objectify 存储在 Google App Engine 数据存储区中的 class 都必须在 class 前加上一个 @Entity 注释。您通常将此注释应用于您自己的 classes,以便在您自己的应用程序或域中使用。在我的 classes 中,我希望能够定义 Option[String] 类型的 class 属性。为此,我需要能够将@Entity 或@Subclass 注释(Objectify 注释)应用于选项class。但那是一种内置的 Scala 语言类型。有没有办法使用隐式 classes 或类型或 Scala 宏对语言执行 "monkey patching" 以允许我在事后将注释添加到内置的 Scala 语言类型?
最简单的解决方案是定义您自己的 class 等效于 Option
和隐式转换 from/to Option
.
否则,Scala 本身无法这样做,但您可以使用字节码操作库之一,如 ASM 或 Javassist。有一个为 ASM here (but it seems incomplete) and one for Javassist here 提供的动态添加注释的示例。 Javassist 似乎更容易使用(没有翻译成 Scala,但它很简单):
import java.lang.reflect.Field;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
public class AddingAnnotationDynamically {
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("scala.Option");
// Without the call to "makePackage()", package information is lost
cp.makePackage(cp.getClassLoader(), pkgName);
ClassFile cfile = cc.getClassFile();
ConstPool cpool = cfile.getConstPool();
AnnotationsAttribute attr =
new AnnotationsAttribute(cpool, AnnotationsAttribute.visibleTag);
Annotation annot = new Annotation(annotationName, cpool);
attr.addAnnotation(annot);
cfile.addAttribute(attr);
// Changes are not persisted without a call to "toClass()"
Class<?> c = cc.toClass();
}
}
我使用 Scala 作为我的语言。我使用 Google Objectify 作为我的持久性 API 将对象存储到 Google App Engine 的数据存储中。任何要通过 Objectify 存储在 Google App Engine 数据存储区中的 class 都必须在 class 前加上一个 @Entity 注释。您通常将此注释应用于您自己的 classes,以便在您自己的应用程序或域中使用。在我的 classes 中,我希望能够定义 Option[String] 类型的 class 属性。为此,我需要能够将@Entity 或@Subclass 注释(Objectify 注释)应用于选项class。但那是一种内置的 Scala 语言类型。有没有办法使用隐式 classes 或类型或 Scala 宏对语言执行 "monkey patching" 以允许我在事后将注释添加到内置的 Scala 语言类型?
最简单的解决方案是定义您自己的 class 等效于 Option
和隐式转换 from/to Option
.
否则,Scala 本身无法这样做,但您可以使用字节码操作库之一,如 ASM 或 Javassist。有一个为 ASM here (but it seems incomplete) and one for Javassist here 提供的动态添加注释的示例。 Javassist 似乎更容易使用(没有翻译成 Scala,但它很简单):
import java.lang.reflect.Field;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
public class AddingAnnotationDynamically {
public static void main(String[] args) throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("scala.Option");
// Without the call to "makePackage()", package information is lost
cp.makePackage(cp.getClassLoader(), pkgName);
ClassFile cfile = cc.getClassFile();
ConstPool cpool = cfile.getConstPool();
AnnotationsAttribute attr =
new AnnotationsAttribute(cpool, AnnotationsAttribute.visibleTag);
Annotation annot = new Annotation(annotationName, cpool);
attr.addAnnotation(annot);
cfile.addAttribute(attr);
// Changes are not persisted without a call to "toClass()"
Class<?> c = cc.toClass();
}
}