javaspringspring-aop

Configure Pointcut for Spring JPA repository methods


I am trying to create an Aspect which runs after every call to save() of Spring JpaRepository. I have defined my Aspect as follows:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
public class ProcessAspect {

    @Autowired
    private ProcessService processService;

    @AfterReturning(value = "execution(* com.domain.control.repository.ProcessDao.save())))",
    returning = "result")
    private void propagateProcess(JoinPoint joinPoint, Object result) {
        log.info("Aspect is working, congratulations. Jointpoint {} , result {}", joinPoint, result.toString());
        Process process = (process) result;

       // do something on the object returned by save()
        processService.createOrUpdateProcess(process);
    }

}

My repository is defined as follows:

@Repository
public interface ProcessDao extends JpaRepository<Process, String>

If I configure it this way then the aspect is not working.

How can I configure my aspect to run after generic JPA repository methods?


Solution

  • First your ProcessDao doesn't have a save method, so it won't match, secondly you have a pointcut with a no-args save method and there is no such thing. Instead you want to use one of the Spring Data repository classes in your pointcut and match 1 argument.

    Something like this

    execution(* org.springframework.data.jpa.repository.JpaRepository+.save(..))))
    

    or to make it more generic

    execution(* org.springframework.data.repository.CrudRepository+.save(..))))
    

    This should make your pointcut match. There is also a saveAll and saveAndFlush so you might want to add a few more pointcuts if you need to intercept those as well.