java - AspectJ - 指定方法的切入点,其参数用类级别注释进行注释

标签 java spring annotations aspectj

在一方面,我想停止在指定的方法上。该方法有一个参数,该参数使用类级别注释进行注释:

注释是:

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

参数是一个类的对象,注释如下:

@Auditable  
public class User {}  

我喜欢检查的方法:

public Object findSingleResultByExample(final Object entity) {}  

这方面不起作用:

@AfterReturning(value="execution(* org.wtp.repository.GenericDao.find*(@org.wtp.aspects.Auditable (*)))",  
argNames = "joinPoint, result",  
returning = "result")  
private void auditFindAnnotation(final JoinPoint joinPoint, final Object result) {}  

最佳答案

首先,您的建议方法必须是public,而不是private。请将其更改为

public void auditFindAnnotation(...)

它不起作用,因为您的切入点拦截带有 @Auditable 参数注释的方法。不过,您的示例方法没有这样的注释。如果方法签名是这样的,那就可以了:

public Object findSingleResultByExample(final @Auditable Object entity) {}

顺便说一句,那么必须删除或扩展 @Target(ElementType.TYPE) 限制才能使代码仍然可以编译。

但我猜你想要的不是匹配参数注释,而是匹配类型注释。那么你的切入点将如下所示(这次 * 周围没有括号):

execution(* org.wtp.repository.GenericDao.find*(@org.wtp.aspects.Auditable *))

但是,这与您的示例方法不匹配,因为它的参数类型不是 UserAuditable 而只是 Object 并且后者确实不携带注释。如果您重载 find* 方法并执行以下操作,您可以看到差异:

package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface Auditable {}
package de.scrum_master.app;

@Auditable
public class User {}
package de.scrum_master.app;

import java.util.ArrayList;

public class Application {
    public Object findSingleResultByExample(final Object entity) {
        return entity;
    }

    public Object findSingleResultByExample(final User entity) {
        return entity;
    }

    public static void main(String[] args) {
        Application application = new Application();
        application.findSingleResultByExample("foo");
        application.findSingleResultByExample(new User());
        application.findSingleResultByExample(new ArrayList<String>());
    }
}
package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AuditAspect {
    @AfterReturning(
        value = "execution(* de.scrum_master.app..find*(@de.scrum_master.app.Auditable *))",
        argNames = "thisJoinPoint, result",
        returning = "result"
    )
    public void auditFindAnnotation(final JoinPoint thisJoinPoint, final Object result) {
        System.out.println(thisJoinPoint + " -> " + result);
    }
}

控制台日志如下所示:

execution(Object de.scrum_master.app.Application.findSingleResultByExample(User)) -> de.scrum_master.app.User@4a574795

更新:为了让整个事情正常工作而不更改或重载任何方法签名,您必须使切入点匹配所有调用,并从方面动态确定类型及其注释通过反射(不太好,但可能)。如果您不明白这个想法,请随时提问。

关于java - AspectJ - 指定方法的切入点,其参数用类级别注释进行注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31073198/

相关文章:

java - 参数的非法修饰符

java des cipher在windows上的不同结果

java - 使用Java解析Java/COBOL/VB等代码

java - Java中是否可以@Query两个微服务数据库?

r - 当轴属于 'date' 类时使用 ggplot2 进行注释

java - 将 Java 对象映射到 @XmlElement 值

java - 从 3.0.1 更新到 3.1 后,Android Studio 未启动

java - 使用 Spring Framework 持久化到 MySQL,Hibernate 和 JPA 失败,没有真正持久化到数据库

Spring Integration 作为独立 ESB 的嵌入式替代方案

java - 带有类型参数的注解属性