Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SpringAOP:有没有办法让@target用于间接注释?_Java_Spring_Aop_Spring Aop - Fatal编程技术网

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的两个嵌套级别