是否可以使用 AOP 框架为方法或成员添加注解?

Can annotations be added to methods or members using AOP frameworks?

我可以使用 AOP(AspectJ、Guice 或其他)向 类 添加我无法修改的注释吗?我的第一个用例是添加持久性和绑定注释。我知道我可以为 JPA 和 JAXB 编写 XML 配置文件,但我不知道有什么方法可以为 JSON 绑定执行此操作。

我找了一些 examples/tutorials 但没有找到任何证明这一点的东西。是否可能,如果可以,有人可以提供一个很好的例子或更好的例子给我一些资源吗?

是的,您可以为此目的使用 AspectJ(引用 AspectJ cheat sheet, see also AspectJ Development Kit Developer's Notebook):

  • declare @type: C : @SomeAnnotation;
    在类型 C.
  • 上声明注解 @SomeAnnotation
  • declare @method: * C.foo*(..) : @SomeAnnotation;
    C 中以 foo.
  • 开头声明的所有方法上声明注解 @SomeAnnotation
  • declare @constructor: C.new(..) : @SomeAnnotation;
    C.
  • 中声明的所有构造函数上声明注解 @SomeAnnotation
  • declare @field: * C.* : @SomeAnnotation;
    C.
  • 中声明的所有字段上声明注释 @SomeAnnotation

以防万一您想问:此功能仅在本机 AspectJ 语法中受支持,在注释样式的 @AspectJ 语法中不受支持。


更新:这是一些示例代码显示

  • 如何向 classes、接口和方法添加注释,
  • 即使是标记为 @Inherited 的注解也只能从 class 继承到子 class,永远不会从接口继承到 class,也永远不会继承到子class方法(许多开发人员不知道的典型 Java 警告,请参阅 了解解释和可能的解决方法),
  • 如何通过 AspectJ 您仍然可以将注释应用于 classes 通过 + subclass 说明符实现接口,例如在 MyInterface+
  • 另一个方面如何立即查看和利用通过 declare @typedeclare @method 等添加的注释

Class 层次结构包括抽象基础 classes 和接口:

package de.scrum_master.app;

public interface MyInterface {
    void doSomething();
    int doSomethingElse(int a, int b);
    String sayHelloTo(String name);
}
package de.scrum_master.app;

public abstract class NormalBase implements MyInterface {
    @Override
    public abstract void doSomething();

    @Override
    public int doSomethingElse(int a, int b) {
        return a + b;
    }

    @Override
    public abstract String sayHelloTo(String name);
}
package de.scrum_master.app;

public class Normal extends NormalBase {
    @Override
    public void doSomething() {
        //System.out.println("Doing something normal");
    }

    @Override
    public String sayHelloTo(String name) {
        return "A normal hello to " + name;
    }

    public void doNothing() {
        //System.out.println("Being lazy in a normal way");
    }
}
package de.scrum_master.app;

public abstract class SpecialBase {
    public abstract void doFoo();
    public abstract void makeBar();
}
package de.scrum_master.app;

public class Special extends SpecialBase implements MyInterface {
    @Override
    public void doSomething() {
        //System.out.println("Doing something special");
    }

    @Override
    public int doSomethingElse(int a, int b) {
        return a * b;
    }

    @Override
    public String sayHelloTo(String name) {
        return "A special hello to " + name;
    }

    @Override
    public void doFoo() {
        //System.out.println("Doing foo");
    }

    @Override
    public void makeBar() {
        //System.out.println("Making bar");
    }

    public int doZot() {
        return 11;
    }

    public String makeBlah() {
        return "Blah";
    }
}
package de.scrum_master.app;

public class SpecialTwo extends SpecialBase {
    @Override
    public void doFoo() {
        //System.out.println("Doing foo");
    }

    @Override
    public void makeBar() {
        //System.out.println("Making bar");
    }

    public String doXxx() {
        return "Xxx";
    }

    public int makeBlah() {
        return 22;
    }
}

驱动程序创建各种对象,调用各种方法:

package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        System.out.println("Normal instance");
        Normal normal = new Normal();
        normal.doSomething();
        normal.doSomethingElse(3, 5);
        normal.sayHelloTo("John");
        normal.doNothing();

        System.out.println("\nNormal instance as NormalBase");
        NormalBase normalBase = normal;
        normalBase.doSomething();
        normalBase.doSomethingElse(3, 5);
        normalBase.sayHelloTo("John");

        System.out.println("\nNormal instance as MyInterface");
        MyInterface myInterface = normal;
        myInterface.doSomething();
        myInterface.doSomethingElse(3, 5);
        myInterface.sayHelloTo("John");

        System.out.println("\nSpecial instance");
        Special special = new Special();
        special.doSomething();
        special.doSomethingElse(7, 8);
        special.doFoo();
        special.doZot();
        special.makeBar();
        special.makeBlah();
        special.sayHelloTo("Jane");

        System.out.println("\nSpecial instance as SpecialBase");
        SpecialBase specialBase = special;
        specialBase.doFoo();
        specialBase.makeBar();

        System.out.println("\nSpecial instance as MyInterface");
        myInterface = special;
        myInterface.doSomething();
        myInterface.doSomethingElse(7, 8);
        myInterface.sayHelloTo("Jane");

        System.out.println("\nSpecialTwo instance");
        SpecialTwo specialTwo = new SpecialTwo();
        specialTwo.doFoo();
        specialTwo.makeBar();
        specialTwo.makeBlah();
        specialTwo.doXxx();

        System.out.println("\nSpecialTwo instance as SpecialBase");
        specialBase = specialTwo;
        specialBase.doFoo();
        specialBase.makeBar();
    }
}

一些标记注释稍后将添加到接口,classes,方面的方法:

package de.scrum_master.app;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InterfaceMarker {}
package de.scrum_master.app;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ClassMarker {}
package de.scrum_master.app;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MethodMarker {}

Aspect adding annotations to interfaces, classes, methods:

package de.scrum_master.aspect;

import de.scrum_master.app.ClassMarker;
import de.scrum_master.app.InterfaceMarker;
import de.scrum_master.app.MethodMarker;
import de.scrum_master.app.MyInterface;
import de.scrum_master.app.SpecialBase;

public aspect AnnotationGenerator {
    declare @type : MyInterface+ : @InterfaceMarker;
    declare @type : SpecialBase : @ClassMarker;
    declare @method : * say*(..) : @MethodMarker;
}

注解 classes 的方面日志记录初始化和注解方法的执行:

package de.scrum_master.aspect;

import de.scrum_master.app.ClassMarker;
import de.scrum_master.app.InterfaceMarker;
import de.scrum_master.app.MethodMarker;

public aspect MarkedObjectLogger {
    before() : @annotation(InterfaceMarker) {
        System.out.println(thisJoinPoint + " -> @InterfaceMarker");
    }

    before() : @annotation(ClassMarker) {
        System.out.println(thisJoinPoint + " -> @ClassMarker");
    }

    before() : @annotation(MethodMarker) && execution(* *(..)) {
        System.out.println(thisJoinPoint + " -> @MethodMarker");
    }
}

控制台日志:

Normal instance
staticinitialization(de.scrum_master.app.NormalBase.<clinit>) -> @InterfaceMarker
staticinitialization(de.scrum_master.app.Normal.<clinit>) -> @InterfaceMarker
execution(String de.scrum_master.app.Normal.sayHelloTo(String)) -> @MethodMarker

Normal instance as NormalBase
execution(String de.scrum_master.app.Normal.sayHelloTo(String)) -> @MethodMarker

Normal instance as MyInterface
execution(String de.scrum_master.app.Normal.sayHelloTo(String)) -> @MethodMarker

Special instance
staticinitialization(de.scrum_master.app.SpecialBase.<clinit>) -> @ClassMarker
staticinitialization(de.scrum_master.app.Special.<clinit>) -> @InterfaceMarker
staticinitialization(de.scrum_master.app.Special.<clinit>) -> @ClassMarker
execution(String de.scrum_master.app.Special.sayHelloTo(String)) -> @MethodMarker

Special instance as SpecialBase

Special instance as MyInterface
execution(String de.scrum_master.app.Special.sayHelloTo(String)) -> @MethodMarker

SpecialTwo instance
staticinitialization(de.scrum_master.app.SpecialTwo.<clinit>) -> @ClassMarker

SpecialTwo instance as SpecialBase

尝试从 declare @type : MyInterface+ 中删除 + 并查看所有提及 @InterfaceMarker 的日志行是如何消失的,因为接口注释确实不会通过实现 classes.