我想为类的每个成员添加注释,其中成员本身用特定注释进行注释。我必须扩展第三方代码,使其为 Hibernate 二级缓存做好准备 - 在本例中,将
@org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_ONLY)
添加到特定字段
我正在使用https://mvnrepository.com/artifact/org.aspectj/aspectjrt/1.9.9.1和https://mvnrepository.com/artifact/org.aspectj/aspectjtools/1.9.9.1
public aspect EntityAspect {
declare @field : (@javax.persistence.OneToOne *) foo.bar.MyEntity : @org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_ONLY);
}
目标:注释
foo.bar.MyEntity
的每个成员,其中具有 @OneToOne
注释,另外还带有 @Cache
。
该模式似乎有效,但 AspectJ 告诉我
[java] [iajc] warning at declare @field : (@javax.persistence.OneToMany *) foo.bar.MyEntity : @org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_ONLY);
[java] [iajc] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[java] [iajc] [..]\EntityAspect.aj:5:0::0 does not match because annotation @javax.persistence.OneToMany has @Target{ElementType.FIELD,ElementType.METHOD} [Xlint:unmatchedTargetKind]
是的,
@OneToMany
注释有@Target
注释 - 我还必须声明吗?又如何?
你的语法有点错误:
declare @field :
(@javax.persistence.OneToOne *) foo.bar.MyEntity :
@org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_ONLY);
有一个问题:括号中的
(@javax.persistence.OneToOne *)
表示目标是带注释的返回类型。您应该省略括号,然后注释将同样应用于字段定义。这是一个用纯 Java + AspectJ 编写的重现器,带有伪造的注释:
package de.scrum_master.app;
public enum CacheConcurrencyStrategy {
NONE, NONSTRICT_READ_WRITE, READ_ONLY, READ_WRITE, TRANSACTIONAL
}
package de.scrum_master.app;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(FIELD)
public @interface Cache {
CacheConcurrencyStrategy usage();
}
package de.scrum_master.app;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Retention(RUNTIME)
@Target(FIELD)
public @interface OneToMany {}
package de.scrum_master.app;
public class Application {
@OneToMany
int id;
String name;
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
System.out.println(Application.class.getDeclaredField("id").getDeclaredAnnotation(Cache.class));
}
}
在没有任何方面的情况下运行它,它将在控制台上打印
null
。现在添加这个方面:
package de.scrum_master.aspect;
import de.scrum_master.app.Cache;
import de.scrum_master.app.OneToMany;
import de.scrum_master.app.CacheConcurrencyStrategy;
import de.scrum_master.app.Application;
public aspect FieldAnnotationAspect {
declare @field :
@OneToMany * Application.* : @Cache(usage = CacheConcurrencyStrategy.READ_ONLY);
}
控制台日志现在显示:
@de.scrum_master.app.Cache(usage=READ_ONLY)
它有效,q.e.d。 😉