Java 不允许基于其他批注的批注

Java 不允许基于其他批注的批注,java,annotations,aspectj,Java,Annotations,Aspectj,我有一个适用于类型(即类级别)的注释和另一个适用于字段变量的注释。如果已应用类型批注,是否有方法禁止字段批注 我正在开发一个AspectJ应用程序,它具有基于注释的切入点。目前,我有两个注释-@Trace和@TraceAll@字段变量允许跟踪,类型允许@TraceAll 如果应用了@Trace,我将使用set()跟踪对应用它的字段变量的写入。如果应用了@TraceAll,我将在()内跟踪所有字段变量和方法 如果用户在一个类上同时应用了两个注释,我不想重复跟踪。我在这里做您的工作,提供一个。这是你

我有一个适用于类型(即类级别)的注释和另一个适用于字段变量的注释。如果已应用类型批注,是否有方法禁止字段批注

我正在开发一个AspectJ应用程序,它具有基于注释的切入点。目前,我有两个注释-@Trace和@TraceAll@字段变量允许跟踪,类型允许@TraceAll

如果应用了@Trace,我将使用set()跟踪对应用它的字段变量的写入。如果应用了@TraceAll,我将在()内跟踪所有字段变量和方法


如果用户在一个类上同时应用了两个注释,我不想重复跟踪。

我在这里做您的工作,提供一个。这是你的免费拍摄,因为你是新来的,所以下次请自己拍摄:

标记注释:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
package de.scrum\u master.app;
导入静态java.lang.annotation.ElementType.TYPE;
导入静态java.lang.annotation.RetentionPolicy.RUNTIME;
导入java.lang.annotation.Retention;
导入java.lang.annotation.Target;
@保留(运行时)
@目标(类型)
public@interface TraceAll{}
package de.scrum\u master.app;
导入静态java.lang.annotation.ElementType.METHOD;
导入静态java.lang.annotation.RetentionPolicy.RUNTIME;
导入java.lang.annotation.Retention;
导入java.lang.annotation.Target;
@保留(运行时)
@目标(方法)
public@interface Trace{}
这里首先想到的是:为什么需要两个注释?为什么不只是一个可以应用于类型和方法的注释
@Trace
?保持简单,有两个注释没有额外的价值。如果将
@Trace
应用于一个类型,那么您是否希望跟踪该类中的所有方法

注释类+驱动程序应用程序:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
package de.scrum\u master.app;
公共类应用程序{
公共无效剂量测定法(){
foo();
bar();
zot();
}
@痕迹
公共void foo(){}
公共无效条(){}
@痕迹
公共void zot(){}
公共静态void main(字符串[]args){
新应用程序().doSomething();
新的SomeClass().doSomething();
}
}
在这里,我复制了您的情况:
应用程序
只使用方法级注释,
SomeClass
混合了这两种注释类型

原始方面:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
由于您没有显示任何代码,我不得不猜测您在方面做了什么。我想是这样的:

package de.scrum\u master.aspect;
导入de.scrum_master.app.Trace;
导入de.scrum_master.app.TraceAll;
公共方面跟踪{
before():@target(TraceAll)和&execution(**(..){
System.out.println(此连接点);
}
before():@注释(跟踪)和执行(**(..){
System.out.println(此连接点);
}
}
这将导致您在问题中描述的问题:

原始特性的控制台日志:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
执行(void de.scrum\u master.app.Application.foo())
执行(void de.scrum\u master.app.Application.zot())
执行(void de.scrum\u master.app.SomeClass.doSomething())
执行(void de.scrum\u master.app.SomeClass.foo())
执行(void de.scrum\u master.app.SomeClass.foo())
执行(void de.scrum\u master.app.SomeClass.bar())
执行(void de.scrum_master.app.SomeClass.zot())
执行(void de.scrum_master.app.SomeClass.zot())
我们可以看到,这两个通知都会发出,并且
SomeClass.foo()
以及
SomeClass.zot()
会被记录两次。这就是你想要避免的,对吗

以下是一种在用户执行此操作时触发编译错误的方法:

改进的方面:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
package de.scrum\u master.aspect;
导入de.scrum_master.app.Trace;
导入de.scrum_master.app.TraceAll;
公共方面跟踪{
before():@target(TraceAll)和&execution(**(..){
System.out.println(此连接点);
}
before():@注释(跟踪)和执行(**(..){
System.out.println(此连接点);
}
声明错误:执行(@Trace*(@TraceAll*).*(..)
:“不要将@TraceAll和@Trace注释组合在一起”;
}
现在类
SomeClass
不再编译,直到方法注释被删除,只留下类型注释。在Eclipse中,它如下所示:

但实际上,有一种更简单的方法可以避免双重日志记录:

改进的方面,迭代2:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
只需通过
| |
运算符将这两个建议组合成一个逻辑OR

package de.scrum\u master.aspect;
导入de.scrum_master.app.Trace;
导入de.scrum_master.app.TraceAll;
公共方面跟踪{
before():(@target(TraceAll)| |@annotation(Trace))&执行(**(..){
System.out.println(此连接点);
}
}
改进方面的控制台日志,迭代2:

package de.scrum_master.app;

@TraceAll
public class SomeClass {
  public void doSomething() {
    foo();
    bar();
    zot();
  }

  @Trace
  public void foo() {}

  public void bar() {}

  @Trace
  public void zot() {}
}
执行(void de.scrum\u master.app.Application.foo())
执行(void de.scrum\u master.app.Application.zot())
执行(void de.scrum\u master.app.SomeClass.doSomething())
执行(void de.scrum\u master.app.SomeClass.foo())
执行(void de.scrum\u master.app.SomeClass.bar())
执行(void de.scrum_master.app.SomeClass.zot())
看到了吗?在不强制用户按您强加给他们的规则玩游戏的情况下,不再重复登录。为什么不同时使用这两种注释呢?也许开发人员总是想跟踪某些方法。为了进行调试,她临时添加了一个类型级别的注释,而不希望强制删除所有方法级别的注释,因为她可能会忘记以后再添加它们

迭代3:只有一个注释

现在,我们只使用一个注释,如下所示:

package de.scrum\u master.app;
导入静态java.lang.annotation.ElementType.METHOD;
导入静态java.lan