自定义注释的Spring AOP切入点在内部静态类中不起作用

J4mes先生:

目前,我有以下切入点。

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    @Aspect
    @Component
    public static class MyAnnotationAspect {
        @Pointcut("execution(* (@com.test.MyAnnotation *).*(..))")
        public void methodInMyAnnotationType() {}

        @Around("methodInMyAnnotationType()")
        public Object annotate(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("AOP WORKING");
            return pjp.proceed();
        }
    }
}

当我如下添加@MyAnnotation根级别的类时,它工作正常

@MyAnnotation
@Service
public class ShiftModule {
    @Resource
    private ShiftModule self;

    /* Executing anything using self.method() triggers the Aspect
     * for @MyAnnotation perfectly
     */
}

如果我在内部静态类上添加注释,则它也不起作用。

@Service
public class ShiftModule {
    @Service
    @MyAnnotation
    public class AnnotatedShiftModule extends ShiftModule {}

    @Resource
    private AnnotatedShiftModule self;

    /* Executing anything using self.method() does NOT trigger the 
     * Aspect for @MyAnnotation or even framework's annotations
     * like @Async
     */
}

如果我在接口上使用此技术,它将起作用。

@Repository
public interface OrderRepo extends JpaRepository<Order,Long> {
    @Repository("annotatedOrderRepo")
    @MyAnnotation
    public interface AnnotatedOrderRepo extends OrderRepo {}
}

如果您能向我展示如何使其与类和Spring Bean一起使用,我将不胜感激。

J4mes先生:

在深入研究AOP主题之后,我终于找到了一个可行的解决方案。

最初,我使用以下切入点。

@Aspect
@Component
public static class MyAnnotationAspect {
    /**
     * Matches the execution of any methods in a type annotated with @MyAnnotation.
     */
    @Pointcut("execution(* (@com.test.MyAnnotation *).*(..))")
    public void methodInMyAnnotationType() {}

    /**
     * Matches the execution of any methods annotated with @MyAnnotation.
     */
    @Pointcut("execution(@com.test.MyAnnotation * *.*(..))")
    public void methodAnnotatedWithMyAnnotation() {}

    @Around("methodInMyAnnotationType() || methodAnnotatedWithMyAnnotation()")
    public Object aop(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("AOP IS WORKING");
        return pjp.proceed;
    }
}

我了解到,methodInMyAnnotationType切入点只有在我@MyAnnotation实际拥有该方法的类的情况下才有效。但是,如果将注释放在扩展了类A的类B上,则AOP无法截获类A的方法。

我发现一种可能的解决方案如下。

@Pointcut("execution(* *(..)) && @this(com.test.MyAnnotation)")

这意味着切入点适用于当前类和父类中的所有方法,并且当前类必须使用注释@MyAnnotation看起来很有希望。不幸的是,Spring AOP不支持@this产生的切入点原语UnsupportedPointcutPrimitiveException

在深入探讨的主题之后this,我发现了target原语的存在并提出了以下解决方案。

@Pointcut("execution(@com.test.MyAnnotation * *.*(..))")
public void annotatedMethod() {}

@Pointcut("execution(* (@com.test.MyAnnotation *).*(..))")
public void annotatedClass() {}

@Pointcut("execution(* *(..)) && target(com.test.MyAnnotable)")
public void implementedInterface() {}

@Around("annotatedMethod() || annotatedClass() || implementedInterface()")
public Object aop(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("AOP IS WORKING");
    return pjp.proceed;
}

这意味着切入点适用于当前类和父类中的所有方法。此外,该方法必须用标记@MyAnnotation@MyAnnotation或者包含该方法的类用标记或者具有该方法的对象必须是marker接口的实例MyAnnotable看起来不错,可以正常工作。

我的最后一堂课实施看起来像这样。

@Service
public class ShiftModule {
    @Service
    public class Annotated extends ShiftModule implements MyAnnotable {}

    @Resource
    private ShiftModule.Annotated self;
}

附加信息:

在实验期间,我确实尝试了以下切入点。

@Pointcut("@annotation(com.test.MyAnnotation)")
public void annotatedMethod() {}

@Pointcut("@within(com.test.MyAnnotation)")
public void annotatedClass() {}

@Pointcut("target(com.test.MyAnnotable)")
public void implementedInterface() {}

@Around("execution(* *(..)) && (annotatedMethod() || annotatedClass() || implementedInterface()")
public Object aop(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println("AOP IS WORKING");
    return pjp.proceed;
}

我发现它不适用于带注释的内部接口,这意味着下面的代码将停止工作。AOP方面根本没有任何影响。

@Repository
public interface OrderRepo extends JpaRepository<Order,Long> {
    @Repository("annotatedOrderRepo")
    @MyAnnotation
    public interface Annotated extends OrderRepo {}
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

切入点在Spring AOP中如何工作?

Spring AOP自定义注释

在Spring中实现自定义注释

Java-Spring AOP切入点不起作用

Spring-AOP 切入点不起作用?

Spring Controller:结合了Spring注释的自定义注释不起作用

在Spring Boot环境中实现自定义注释

@Around 切入点未调用自定义注释

Spring AOP自定义注释在Handler Interceptor类中给出错误

无法在Spring AOP中检测类级别的自定义注释

Spring Boot-表单上的自定义验证注释不起作用

接口上的Aspectj Spring切入点不起作用

Spring AOP:创建切入点,检查父类注释

自定义Spring AOP注释不适用于默认方法

在类级别带有RequestMapping注释的Spring Boot Actuator自定义RestControllerEndpoint

如何在Spring Boot中修复错误自定义注释?

Spring AOP多个切入点和建议,但只有最后一个在起作用

细粒度的Spring自动装配不起作用(@Autowired,带有附加的自定义注释)

带注释的类的所有公共方法(包括父类方法)的Spring AOP切入点

Spring AOP的参考来自各阶层在任何包中的所有方法,切入点在某个字符串结束

带有 Gradle 切入点或建议的 AspectJ 不起作用 - 不使用 spring 或 android

@SuppressWarnings和其他自定义注释在内部如何工作?

SonarQube:创建自定义规则以在类中获取自定义注释

@mock注释与Mockito中的自定义Answer类

Spring AOP切入点在列表内可用时,不会在对象的方法调用上触发

自定义MessageConverter在Spring Boot中不起作用

AOP在覆盖方法上应用自定义注释

在Controller类中使用自定义注释时,自动装配不起作用

Spring AOP:从切入点中排除最终类和枚举