【问题标题】:Is it possible to monkey patch a scala final class with an annotation?是否可以用注释修补 scala final 类?
【发布时间】:2015-09-18 21:08:42
【问题描述】:
我使用 Scala 作为我的语言。我使用 Google Objectify 作为我的持久性 API 来将对象存储到 Google App Engine 的数据存储中。任何要通过 Objectify 存储在 Google App Engine Datastore 中的类都必须有一个 @Entity 注释作为该类的前缀。您通常将此注释应用于您自己的类,以便在您自己的应用程序或域中使用。在我的一个类中,我希望能够定义一个 Option[String] 类型的类属性。为此,我需要能够将 @Entity 或 @Subclass 注释(Objectify 注释)应用于 Option 类。但这是一种内置的 Scala 语言类型。有没有办法使用隐式类或类型或 Scala 宏对语言进行“猴子修补”,以便我在事后将该注释添加到内置的 Scala 语言类型?
【问题讨论】:
标签:
java
scala
annotations
objectify
【解决方案1】:
最简单的解决方案是定义您自己的等价于Option 的类以及与Option 之间的隐式转换。
否则,Scala 本身无法这样做,但您可以使用 ASM 或 Javassist 等字节码操作库之一。有一个为 ASM here(但似乎不完整)和 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();
}
}