为了账号安全,请及时绑定邮箱和手机立即绑定

拦截 Spring AOP 或 AspectJ 中带注解的类和方法

拦截 Spring AOP 或 AspectJ 中带注解的类和方法

GCT1015 2023-01-05 17:01:22

所以我有一个自定义注释


@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Inherited

@Documented

public @interface Intercepted {}

我想用它来将方面编织到方法中(AspectJ,@annotation(Intercepted))。


这个想法是,当我@Intercepted直接注释方法时,我将方面编织进去——那部分工作——或者如果我注释类,应该将方面编织到它的所有(公共)方法中——那部分不起作用。


此外,如果我注释一个类及其方法之一,则方面应该只编织一次,方法级别的注释覆盖类级别的注释。


本质上,我想要一个“如果有类级注释,则添加类级注释,但前提是还没有方法级注释”。


我怎么做?


查看完整描述

1 回答

?
白猪掌柜的

TA贡献1640条经验 获得超9个赞

这是一个 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())


查看完整回答
反对 回复 2023-01-05

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信