AspectJ - 指定方法的切入点,带有使用类级别注释注释的参数

时间:2015-06-26 12:28:05

标签: 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) {}  

1 个答案:

答案 0 :(得分:1)

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

public void auditFindAnnotation(...)

它无法正常工作,因为您的切入点会使用@Auditable参数注释拦截方法。但是,您的示例方法没有这样的注释。如果方法签名是这样的话,它会起作用:

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

BTW,然后必须删除或扩展@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

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