是否可以用注释猴子修补 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();
    }
}