1

I'm trying to intercept all classes that contains a specific word in their package name... something as below:

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

I have all the classes in the packages to intercept:

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);

In short, i would like to intercept all the methods in the classes that belong to the

package *service*

I am trying to get this working from past many days.

  • Should it match package folders _named_ `service` or package folders _containing_ `service` too (like `com.test.fooservice1.Type`)? – Nándor Előd Fekete May 20 '16 at 11:11
  • @NándorElődFekete i would like to make this a library so that it can scan all the packages in the client side and intercept clients packages which contain the keyword "service" – Prathiba530 May 20 '16 at 13:17
  • @NándorElődFekete keyword "service" can be anywhere in the package like `com.domain.test.service.Type(..)` and `com.test.service.impl.HelloWorld(..)` – Prathiba530 May 20 '16 at 13:23

3 Answers3

0

Try this. Perhaps you have to exclude your aspect classes to avoid endless loops. This example catch all methods with com..login..* in package

@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);
        }
    }
}
Frank M.
  • 997
  • 1
  • 10
  • 19
0

I think you can capture what you need with a pointcut like this:

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

The three within clauses capture the three alternatives:

  • within(*..service..*.*): 'service' is somewhere in the package name but not at the start or end
  • within(service..*.*): 'service' is at the start of the package name (maybe this can't happen in your scenario)
  • within(*..service.*)): 'service' is at the end of the package name

If you need to capture serviceFoo variants you could add further wildcards around service (I think): within(*..*service*.*)

Andy Clement
  • 2,510
  • 16
  • 11
0

You should use a pointcut expression like this:

within(your.base.package..service..*)
  • restrict to at least your base package (typically this is not an issue)
  • match 'service' keyword in your package name at any level

for example, this will match those classes :

  • your.base.package.service.ServiceClass
  • your.base.package.service.customer.ServiceClass
  • your.base.package.internal.service.ServiceClass
  • your.base.package.internal.service.customer.ServiceClass
Donatello
  • 3,486
  • 3
  • 32
  • 38