Java SpringAOP:有没有办法让@target用于间接注释?
我有一个注解:Java SpringAOP:有没有办法让@target用于间接注释?,java,spring,aop,spring-aop,Java,Spring,Aop,Spring Aop,我有一个注解: @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE}) public @interface MyAnnotation { } 我用它注释Spring MVC控制器: @MyAnnotation public class TestController { ... } 然后,我添加了一条建议,其中包含以下内容: @Pointcut
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface MyAnnotation {
}
我用它注释Spring MVC控制器:
@MyAnnotation
public class TestController { ... }
然后,我添加了一条建议,其中包含以下内容:
@Pointcut("@target(MyAnnotation)")
public void annotatedWithMyAnnotation() {}
@Around("annotatedWithMyAnnotation()")
public Object executeController(ProceedingJoinPoint point) throws Throwable { ... }
已成功调用Advice的方法
现在我有一堆控制器共享相同的注释,我想使用一个原型注释来对它们进行分组
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@MyAnnotation
... other annotations
public @interface StereotypeAnnotation {
}
然后我用@StereotypeAnnotation
注释我的控制器:
@StereotypeAnnotation
public class TestController { ... }
控制器不再直接包含@MyAnnotation
问题是在这种情况下,@target
切入点停止匹配我的控制器,不建议它们
有没有办法定义一个切入点来匹配具有这种间接注释的控制器?我用纯AspectJ重新创建了这种情况,因为我不太喜欢Spring AOP。这就是为什么我在通知的切入点前面添加了一个额外的
execution(**(..)&&
,以避免匹配SpringAOP中不可用的其他连接点,例如call()
。如果您愿意,可以在SpringAOP中删除它
好的,让我们按照您描述的方式创建此情况:
package de.scrum\u master.app;
导入java.lang.annotation.ElementType;
导入java.lang.annotation.Inherited;
导入java.lang.annotation.Retention;
导入java.lang.annotation.RetentionPolicy;
导入java.lang.annotation.Target;
@继承的
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.TYPE,ElementType.ANNOTATION\u TYPE})
public@interface MyAnnotation{}
package de.scrum\u master.app;
导入java.lang.annotation.ElementType;
导入java.lang.annotation.Retention;
导入java.lang.annotation.RetentionPolicy;
导入java.lang.annotation.Target;
@目标({ElementType.TYPE,ElementType.ANNOTATION\u TYPE})
@保留(RetentionPolicy.RUNTIME)
@MyAnnotation
public@interface注释{}
package de.scrum\u master.app;
@MyAnnotation
公共类测试控制器{
公共无效剂量测定法(){
System.out.println(“做某事”);
}
}
package de.scrum\u master.app;
@原型注释
公共类另一控制器{
公共无效剂量测定法(){
System.out.println(“做另一件事”);
}
}
这是我们的纯Java驱动程序应用程序(无Spring):
package de.scrum\u master.app;
公共类应用程序{
公共静态void main(字符串[]args){
新的TestController().doSomething();
新的另一个控制器();
}
}
这是一个方面:
package de.scrum\u master.aspect;
导入org.aspectj.lang.ProceedingJoinPoint;
导入org.aspectj.lang.annotation.Around;
导入org.aspectj.lang.annotation.Aspect;
导入org.aspectj.lang.annotation.Pointcut;
@面貌
公共类元注释方面{
@切入点(
“@target(de.scrum_master.app.MyAnnotation)|”+
“@target(de.scrum\u master.app.annotation)”
)
公共无效解决方案a(){}
@围绕(“执行(**(..)&&solutionA()”)
公共对象executeController(ProceedingJoinPoint点)抛出可丢弃的{
系统输出打印项次(点);
返回点。继续();
}
}
日志输出将是:
执行(void de.scrum\u master.app.TestController.doSomething())
做某事
执行(void de.scrum\u master.app.AnotherController.doSomething())
做另一件事
到目前为止,一切顺利。但是如果我们添加另一个嵌套级别呢
package de.scrum\u master.app;
导入java.lang.annotation.ElementType;
导入java.lang.annotation.Retention;
导入java.lang.annotation.RetentionPolicy;
导入java.lang.annotation.Target;
@目标(ElementType.TYPE)
@保留(RetentionPolicy.RUNTIME)
@原型注释
public@interface SubStereotypeAnnotation{}
package de.scrum\u master.app;
@子类型注释
公共类YetAnotherController{
公共无效剂量测定法(){
System.out.println(“做另一件事”);
}
}
package de.scrum\u master.app;
公共类应用程序{
公共静态void main(字符串[]args){
新的TestController().doSomething();
新的另一个控制器();
新的YetAnotherController().doSomething();
}
}
然后切入点将不再匹配嵌套的元/原型注释:
执行(void de.scrum\u master.app.TestController.doSomething())
做某事
执行(void de.scrum\u master.app.AnotherController.doSomething())
做另一件事
做另一件事
我们必须明确地将|@target(de.scrum_master.app.StereotypeAnnotation)
添加到切入点,也就是说,我们必须知道层次结构中的所有注释类名。有一种方法可以通过使用in()
切入点指示器的特殊语法来克服此问题,另请参见:
package de.scrum\u master.aspect;
导入org.aspectj.lang.ProceedingJoinPoint;
导入org.aspectj.lang.annotation.Around;
导入org.aspectj.lang.annotation.Aspect;
导入org.aspectj.lang.annotation.Pointcut;
@面貌
公共类元注释方面{
@切入点(
“在(@de.scrum_master.app.MyAnnotation*)||内”+
“在(@(@de.scrum_master.app.MyAnnotation*)*)||”+
“在(@(@(@de.scrum_master.app.MyAnnotation*)*)内”
)
公共无效解决方案B(){}
@围绕(“执行(**(..)&&solutionB()”)
公共对象executeController(ProceedingJoinPoint点)抛出可丢弃的{
系统输出打印项次(点);
返回点。继续();
}
}
控制台日志更改为:
执行(void de.scrum\u master.app.TestController.doSomething())
做某事
执行(void de.scrum\u master.app.AnotherController.doSomething())
做另一件事
执行(void de.scrum\u master.app.YetAnotherController.doSomething())
做另一件事
看到了吗?我们只需要知道一个注释类,即MyAnnotation
,就可以覆盖me的两个嵌套级别