1

I have a Spring-Data repository like this:

package com.example.demo;

@RepositoryRestResource
public interface FooRepository extends JpaRepository<Foo, Long> {

    @Override
    <S extends Foo> S save(S entity);

    @Override
    <S extends Foo> List<S> saveAll(Iterable<S> entities);

}

And an aspect like this:

@Aspect
@Component
public class FooAspect {

    @Before("execution(* org.springframework.data.repository.CrudRepository.save(*))")
    void crudSaveBefore(JoinPoint joinPoint) throws Throwable {
        System.out.println("crud save");
    }

    @Before("execution(* com.example.demo.FooRepository.save(*))")
    void fooSaveBefore(JoinPoint joinPoint) throws Throwable {
        System.out.println("foo save");
    }

    @Before("execution(* org.springframework.data.repository.CrudRepository.saveAll(*))")
    void crudSaveAll(JoinPoint joinPoint) throws Throwable {
        System.out.println("crud save all");
    }

    @Before("execution(* com.example.demo.FooRepository.saveAll(*))")
    void fooSaveAll(JoinPoint joinPoint) throws Throwable {
        System.out.println("foo save all");
    }

}

When I run fooRepository.save(..), in the console I see: foo save

When I run fooRepository.saveAll(..), in the console I see foo save all and crud save all

I was expecting saveAll to only intercept on the FooRepository flavor since I am point-cutting the package.class.method directly. This seems to have worked for save, but not saveAll.

Is this because the args in saveAll are Iterable? Or some kind of type-erasure happening here with the generics? Something else?

Zack
  • 3,819
  • 3
  • 27
  • 48
  • I am pretty sure I could help you if I knew how to run this code. Please provide an [MCVE](https://stackoverflow.com/help/mcve), ideally on GitHub. Then I will take a look. (I am a Spring noob, but kind of an AOP expert.) – kriegaex Jul 11 '20 at 05:48
  • Apparently you can combine pointcut expressions with logical operators AND, NOT, OR. That way, you could make the expressions in your @Before annotations stricter e.g. "Match FooRepo.saveAll but NOT CrudRepo.saveAll". See "Combining Pointcut Expressions" here: https://www.baeldung.com/spring-aop-pointcut-tutorial – Colm Bhandal Jul 27 '21 at 17:42

1 Answers1

3

It seems AOP issue. For proxy FooRepository.saveAll it invokes CrudRepository.saveAll @Before expression:

AbstractAspectJAdvice 683 AOP pointcut

Valijon
  • 12,667
  • 4
  • 34
  • 67