34

I have this working code for a specific package, but i want to configure it for all controllers, service and dao packages Eg

  • com.abc.xyz.content.controller
  • com.abc.xyz.content.service
  • com.abc.xyz.content.dao
  • com.abc.xyz.category.controller
  • com.abc.xyz.category.service
  • com.abc.xyz.category.dao

and so on. . . that is the base package of my project, can someone please help how I can go about doing it so that it works for all classes of my web project including controllers, thanks in advance. . .

package com.abc.xyz.utilities;

import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect
{
    private Log log = LogFactory.getLog(this.getClass());

    @Pointcut("execution(* com.abc.xyz.content.service..*(..))")
    protected void loggingOperation()
    {
    }

    @Before("loggingOperation()")
    @Order(1)
    public void logJoinPoint(JoinPoint joinPoint)
    {
    log.info("Signature declaring type : " + joinPoint.getSignature().getDeclaringTypeName());
    log.info("Signature name : " + joinPoint.getSignature().getName());
    log.info("Arguments : " + Arrays.toString(joinPoint.getArgs()));
    log.info("Target class : " + joinPoint.getTarget().getClass().getName());
    }

    @AfterReturning(pointcut = "loggingOperation()", returning = "result")
    @Order(2)
    public void logAfter(JoinPoint joinPoint, Object result)
    {
    log.info("Exiting from Method :" + joinPoint.getSignature().getName());
    log.info("Return value :" + result);
    }

    @AfterThrowing(pointcut = "execution(* com.abc.xyz.content.service..*(..))", throwing = "e")
    @Order(3)
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e)
    {
    log.error("An exception has been thrown in " + joinPoint.getSignature().getName() + "()");
    log.error("Cause :" + e.getCause());
    }

    @Around("execution(* com.abc.xyz.content.service..*(..))")
    @Order(4)
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable
    {
    log.info("The method " + joinPoint.getSignature().getName() + "() begins with " + Arrays.toString(joinPoint.getArgs()));
    try
    {
        Object result = joinPoint.proceed();
        log.info("The method " + joinPoint.getSignature().getName() + "() ends with " + result);
        return result;
    }
    catch (IllegalArgumentException e)
    {
        log.error("Illegal argument " + Arrays.toString(joinPoint.getArgs()) + " in " + joinPoint.getSignature().getName() + "()");
        throw e;
    }
    }

}

3 Answers 3

72

How about one of these alternatives?

A) General execution pointcut with package restrictions:

execution(* *(..)) &&
(
    within(com.abc.xyz..controller..*) ||
    within(com.abc.xyz..service..*) ||
    within(com.abc.xyz..dao..*)
)

B) Package-restricted execution pointcuts:

execution(* com.abc.xyz..controller..*(..)) ||
execution(* com.abc.xyz..service..*(..)) ||
execution(* com.abc.xyz..dao..*(..))

I prefer B, by the way, just because it is a bit shorter and easier to read. As you have probably guessed, the .. notation means "any package or subpackage", whereas * at the end of the expression after .. means "any method in any class".

3
  • So basically it is possible to define all within() pointcut expressions using other pointcut desginators, right? I think for nested classes, within() can simplify the expressions (sometimes extremely), but otherwise it is just a convenient pointcut designator. Commented Jul 24, 2016 at 7:53
  • 1
    Theoretically yes, but it often just does not make sense. I would always choose the (combination of) pointcut(s) most clearly expressing my intent as a developer. Good pointcuts can be read like a sentence such as: "Within packages x and y, pick all public, non-static methods in classes annotated by @Z, but only if they return values of type A."
    – kriegaex
    Commented Jul 24, 2016 at 8:39
  • Late amendment to my previous comment: within matches many more joinpoint types than just execution, e.g. call, get, set, initialization, staticinitialization. It also matches constructor execution which has different syntax than method execution when using execution pointcuts.
    – kriegaex
    Commented Nov 11, 2021 at 10:27
10

You just need to change your point cut to something like this :

@Pointcut("within(com.abc.*)")

Further reading - https://docs.spring.io/spring/docs/2.0.x/reference/aop.html

4
  • 1
    Okay. For controllers you can do something like stackoverflow.com/questions/2011089/…
    – Vimal Bera
    Commented Sep 23, 2014 at 10:15
  • No mapping found for HTTP request with URI [/xyz-web-vodafone/content.showContentWorkbench.htm] in DispatcherServlet with name 'dispatcher'
    – Mohan Seth
    Commented Sep 23, 2014 at 10:27
  • firstly can I atleast configure it for services and dao packages, can U tell me how to achieve that
    – Mohan Seth
    Commented Sep 23, 2014 at 10:30
  • Its pretty simple. What you need to do is provide expression within @Pointcut itself as mentioned in answer.
    – Vimal Bera
    Commented Sep 23, 2014 at 12:06
1

Another alternative is to use

@Pointcut("bean(*Controller)")

But naming of your beans should be corresponding

Not the answer you're looking for? Browse other questions tagged or ask your own question.