【问题标题】:@AspectJ pointcut for execute methods of a package that contains keyword service包含关键字 service 的包的执行方法的 @AspectJ 切入点
【发布时间】:2016-05-20 05:16:55
【问题描述】:

我正在尝试拦截所有包名中包含特定单词的类...如下所示:

@Pointcut("execution(* *..service..*.*(..))")

我有要拦截的包中的所有类:

com.domain.model.user.service.save(User user);
com.domain.model.user.service.impl.save(XPTO xpto);
com.domain.model.foo.service.HelloWorld.getMessage(Foo foo);

简而言之,我想截取类中所有属于该类的方法

package *service*

我正试图从过去的很多天开始这项工作。

【问题讨论】:

  • 是否应该匹配命名 service的包文件夹或包含 service的包文件夹(如com.test.fooservice1.Type)?
  • @NándorElődFekete 我想让它成为一个库,以便它可以扫描客户端中的所有包并拦截包含关键字“服务”的客户端包
  • @NándorElődFekete 关键字“服务”可以在包中的任何位置,例如 com.domain.test.service.Type(..)com.test.service.impl.HelloWorld(..)

标签: aspectj spring-aop


【解决方案1】:

试试这个。也许您必须排除方面类以避免无限循环。此示例捕获包中带有 com..login..* 的所有方法

@Aspect
@SuppressAjWarnings({ "adviceDidNotMatch" })
public class AllMethodsAspect {
    private static Map<String, Long> beforeTimestamps = new HashMap<>();

    @Pointcut("!within(aspects..*)"
                    + " && (!execution(* org..*           (..))     && !within(org..*)           && !call(* org..*         (..)) )"
                    + " && (!execution(* java..*          (..))     && !within(java..*)          && !call(* java..*        (..)) )"
                    + " && (!execution(* javax..*         (..))     && !within(javax..*)         && !call(* javax..*       (..)) )"
                    + " && (!execution(* sun..*           (..))     && !within(sun..*)           && !call(* sun..*         (..)) )"
                    + " && execution(* com..login..*(..))")
    public void methodCall() {
    }

    @Before("methodCall()")
    public void before(JoinPoint joinPoint) {
        beforeMethodCall(joinPoint);
    }

    @AfterReturning(pointcut = "methodCall()", returning = "returnObject")
    public void after(JoinPoint joinPoint, Object returnObject) {
        afterMethodCall(joinPoint, returnObject);
    }

    @AfterThrowing(pointcut = "methodCall()", throwing = "throwable")
    public void throwing(JoinPoint joinPoint, Throwable throwable) {
        afterThrowingMethodCall(joinPoint, throwable);
    }

    void beforeMethodCall(JoinPoint joinPoint) {
        try {
            long start = System.currentTimeMillis();
            beforeTimestamps.put(joinPoint.toString() + " - " + Thread.currentThread().getName(), Long.valueOf(start));
            LOG.info(".before " + joinPoint);
        } catch (Exception e) {
            LOG.error(".before Exception " + e);
        }
    }

    void afterMethodCall(JoinPoint joinPoint, Object returnObject) {
        afterMethodCall(joinPoint, returnObject, 0);
    }

    void afterMethodCall(JoinPoint joinPoint, Object returnObject, int depth) {
        try {
            long start = beforeTimestamps.get(joinPoint.toString() + " - " + Thread.currentThread().getName()).longValue();
            beforeTimestamps.remove(joinPoint.toString() + " - " + Thread.currentThread().getName());

            long duration = System.currentTimeMillis() - start;
            Signature signature = joinPoint.getSignature();
            if (signature instanceof MethodSignature) {
                Class<?> returnType = ((MethodSignature) signature).getReturnType();
                LOG.info(".after " + joinPoint + " " + duration + "ms" + (void.class == returnType ? "" : " [" + returnObject + "]"));
            } else if (signature instanceof ConstructorSignature) {
                LOG.info(".after " + joinPoint + " " + duration + "ms Constructor");
            } else if (signature instanceof FieldSignature) {
                LOG.info(".after " + joinPoint + " " + duration + "ms Field");
            } else {
                LOG.info(".after " + joinPoint + " " + duration + "ms unknown");
            }
        } catch (Exception e) {
            LOG.error(".after Exception " + e);
        }
    }

    void afterThrowingMethodCall(JoinPoint joinPoint, Throwable throwable) {
        try {
            Long startAsLong = beforeTimestamps.get(joinPoint.toString() + " - " + Thread.currentThread().getName());
            long start = startAsLong == null ? 0 : startAsLong.longValue();
            beforeTimestamps.remove(joinPoint.toString() + " - " + Thread.currentThread().getName());

            long duration = System.currentTimeMillis() - start;
            LOG.info(".fail " + joinPoint.toString() + " " + duration + " ms - " + throwable.getMessage());
        } catch (NullPointerException e) {
            LOG.info(".fail NullPointerException " + "unknown - " + throwable.getMessage());
        }
    }

    static final class LOG {
        static void info(String loggingData) {
            System.err.println(new Date() + " " + loggingData);
        }

        static void error(String loggingData) {
            System.err.println(new Date() + " " + loggingData);
        }
    }
}

【讨论】:

    【解决方案2】:

    我认为你可以用这样的切入点来捕捉你需要的东西:

    before(): execution(* *(..)) && 
              (within(*..service..*.*) || within(service..*.*) || within(*..service.*)) {}
    

    三个 inside 子句捕获了三个备选方案:

    • within(*..service..*.*): 'service' 在包名中的某个位置,但不在开头或结尾
    • within(service..*.*): 'service' 位于包名的开头(在你的场景中这可能不会发生)
    • within(*..service.*)): 'service' 在包名的末尾

    如果您需要捕获 serviceFoo 变体,您可以在服务周围添加更多通配符(我认为):within(*..*service*.*)

    【讨论】:

      【解决方案3】:

      你应该使用这样的切入点表达式:

      within(your.base.package..service..*)
      
      • 至少限制在您的基础包(通常这不是问题)
      • 在任何级别的包名称中匹配“服务”关键字

      例如,这将匹配那些类:

      • your.base.package.service.ServiceClass
      • your.base.package.service.customer.ServiceClass
      • your.base.package.internal.service.ServiceClass
      • your.base.package.internal.service.customer.ServiceClass

      【讨论】:

        猜你喜欢
        • 2011-12-09
        • 1970-01-01
        • 2014-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-31
        相关资源
        最近更新 更多