拦截注解 类 和 Spring AOP 或 AspectJ 中的方法
Intercept annotated classes and methods in Spring AOP or AspectJ
所以我有一个自定义注释
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Intercepted {}
我想用来将方面编织到方法中(AspectJ,@annotation(Intercepted)
)。
我的想法是,当我直接注释方法 @Intercepted
时,我将方面编织到——那部分工作——或者如果我注释 class,方面应该编织到所有它的 (public) 方法——那部分没有。
此外,如果我注释 class 和 它的方法之一,方面应该只编织一次,方法级注释覆盖 class-一级.
本质上,我想要一个 "add the class-level annotation if there's a class-level annotation, but only if there isn't already a method-level annotation."
我该怎么做?
这是一个 AspectJ 示例。 Spring AOP 中的切入点语法相同。
帮手类:
package de.scrum_master.app;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Intercepted {}
package de.scrum_master.app;
@Intercepted
public class AnnotatedClass {
public void doSomething() {}
public void doSomethingElse() {}
}
package de.scrum_master.app;
public class AnnotatedMethod {
@Intercepted
public void doSomething() {}
public void doSomethingElse() {}
}
package de.scrum_master.app;
@Intercepted
public class AnnotatedMixed {
@Intercepted
public void doSomething() {}
public void doSomethingElse() {}
}
驱动程序应用程序(Java SE,无 Spring):
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
// Should be logged
new AnnotatedClass().doSomething();
// Should be logged
new AnnotatedClass().doSomethingElse();
// Should be logged
new AnnotatedMethod().doSomething();
// Should NOT be logged
new AnnotatedMethod().doSomethingElse();
// Should be logged, but only once
new AnnotatedMixed().doSomething();
// Should be logged
new AnnotatedMixed().doSomethingElse();
}
}
看点:
请注意 execution(* *(..)) &&
部分在 Spring AOP 中不是必需的,因为那里只支持方法执行连接点。切入点可能就在 annotatedMethod() || annotatedClass()
那里。在 AspectJ 中,我必须更加精确,否则会记录其他连接点类型。
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AnnotationInterceptor {
@Pointcut("@annotation(de.scrum_master.app.Intercepted)")
public void annotatedMethod() {}
@Pointcut("@within(de.scrum_master.app.Intercepted)")
public void annotatedClass() {}
@Before("execution(* *(..)) && (annotatedMethod() || annotatedClass())")
public void log(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
控制台日志:
execution(void de.scrum_master.app.AnnotatedClass.doSomething())
execution(void de.scrum_master.app.AnnotatedClass.doSomethingElse())
execution(void de.scrum_master.app.AnnotatedMethod.doSomething())
execution(void de.scrum_master.app.AnnotatedMixed.doSomething())
execution(void de.scrum_master.app.AnnotatedMixed.doSomethingElse())
所以我有一个自定义注释
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Intercepted {}
我想用来将方面编织到方法中(AspectJ,@annotation(Intercepted)
)。
我的想法是,当我直接注释方法 @Intercepted
时,我将方面编织到——那部分工作——或者如果我注释 class,方面应该编织到所有它的 (public) 方法——那部分没有。
此外,如果我注释 class 和 它的方法之一,方面应该只编织一次,方法级注释覆盖 class-一级.
本质上,我想要一个 "add the class-level annotation if there's a class-level annotation, but only if there isn't already a method-level annotation."
我该怎么做?
这是一个 AspectJ 示例。 Spring AOP 中的切入点语法相同。
帮手类:
package de.scrum_master.app;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Intercepted {}
package de.scrum_master.app;
@Intercepted
public class AnnotatedClass {
public void doSomething() {}
public void doSomethingElse() {}
}
package de.scrum_master.app;
public class AnnotatedMethod {
@Intercepted
public void doSomething() {}
public void doSomethingElse() {}
}
package de.scrum_master.app;
@Intercepted
public class AnnotatedMixed {
@Intercepted
public void doSomething() {}
public void doSomethingElse() {}
}
驱动程序应用程序(Java SE,无 Spring):
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
// Should be logged
new AnnotatedClass().doSomething();
// Should be logged
new AnnotatedClass().doSomethingElse();
// Should be logged
new AnnotatedMethod().doSomething();
// Should NOT be logged
new AnnotatedMethod().doSomethingElse();
// Should be logged, but only once
new AnnotatedMixed().doSomething();
// Should be logged
new AnnotatedMixed().doSomethingElse();
}
}
看点:
请注意 execution(* *(..)) &&
部分在 Spring AOP 中不是必需的,因为那里只支持方法执行连接点。切入点可能就在 annotatedMethod() || annotatedClass()
那里。在 AspectJ 中,我必须更加精确,否则会记录其他连接点类型。
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AnnotationInterceptor {
@Pointcut("@annotation(de.scrum_master.app.Intercepted)")
public void annotatedMethod() {}
@Pointcut("@within(de.scrum_master.app.Intercepted)")
public void annotatedClass() {}
@Before("execution(* *(..)) && (annotatedMethod() || annotatedClass())")
public void log(JoinPoint thisJoinPoint) {
System.out.println(thisJoinPoint);
}
}
控制台日志:
execution(void de.scrum_master.app.AnnotatedClass.doSomething())
execution(void de.scrum_master.app.AnnotatedClass.doSomethingElse())
execution(void de.scrum_master.app.AnnotatedMethod.doSomething())
execution(void de.scrum_master.app.AnnotatedMixed.doSomething())
execution(void de.scrum_master.app.AnnotatedMixed.doSomethingElse())