java—为SpringAOP注解创建切入点,将注解放在类上,并对类中的每个方法执行建议

pbpqsu0x  于 2021-07-08  发布在  Java
关注(0)|答案(3)|浏览(445)

我想在类级别上有一个注解,它将对注解类中的每个方法执行建议。这有可能吗。
示例:我想注解 OmniDemoService@DoSomethingForMe 我想要方法1和 method2 在执行前记录“看着我”
这个例子不起作用,我也不知道为什么。当我将切入点转换为around并将其与annotation一起使用(同时将annotation elementtype更改为method)时,一切都在方法级别工作。所以我认为这是错误的切入点定义。
注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DoSomethingForMe {
}

建议:

@Aspect
@Component
public class DoSomethingForMeAdvice {

    private static final Logger logger = LoggerFactory.getLogger(DoSomethingForMeAdvice.class);

    @Pointcut("execution(public * *(..)) && @annotation(DoSomethingForMe)")
    public void anyAnnotatedMethod() {
    }

    @Before("anyAnnotatedMethod()")
    public void acquireExecution() {
        logger.info("look at me");
    }
}

用法:

@Service
@DoSomethingForMe
public class OmniDemoService {

    private static final Logger logger = LoggerFactory.getLogger(OmniDemoService.class);

    public void method1() {
            logger.info("---1---");
    }

    public void method2() {
            logger.info("---2---");
    }
}
a6b3iqyw

a6b3iqyw1#

你的问题是你混淆了切入点的定义和建议。
切入点是目标,建议执行你想执行的实际任务。比如说

@Pointcut("@annotation(com.omnidemo.advice.DoSomethingForMe)")
public void anyAnnotatedMethod() {
}

@Before("anyAnnotatedMethod()")
public void logMethodCall(JoinPoint jp) {
    String methodName = jp.getSignature().toShortString();
    logger.info("Executing: " + methodName);
}
ruoxqz4g

ruoxqz4g2#

解决这个问题的方法是在中使用for pointcut

@Pointcut("@within(DoSomethingForMe)")
public void anyAnnotatedMethod() {
}

@Before("anyAnnotatedMethod()")
public void acquireExecution() {
    logger.info("look at me");
}

@j asgarov在评论中提供的解决方案

r1wp621o

r1wp621o3#

看看aspectj快速参考是怎么说的 @annotation() :
主体具有类型注解的任何连接点 SomeAnnotation 你曾经 @annotation(DoSomethingForMe) 但方法执行的“主体”是方法。因此,这意味着任何注解为@dosomethingforme的方法。
使用 @this(DoSomethingForMe) 或者 @target(DoSomethingForMe) .
感谢kriegaex指出这一点 @this 以及 @target 必须在运行时进行评估,这将严重污染代码库(即签入每个方法)。所以下一种方法更好:
如果查看aspectj手册中关于类型模式的部分,您将看到可以直接对类型进行注解。还请记住使用完全限定的类名。那就是:

execution(public * (@com.path.DoSomethingForMe *).*(..))

另外,如果您有这样一个简单的切入点,并且不需要重用它,那么我认为您可以放弃附加方法,直接在建议中使用它:

@Before("execution(public * (@com.path.DoSomethingForMe *).*(..))")

上面写着:“在执行任何带有 @com.path.DoSomethingForMe ,其中“方法执行前”是指“方法内部,开始”。
或者,如果这个切入点对您来说有点太复杂,您可以像这样分离注解匹配和方法匹配,正如j asgarov在他的评论中所建议的:

@Before("execution(public * *(..)) && @within(com.path.DoSomethingForMe)")

相关问题