Q:

Injecting JpaRepository directly

Im looking for a way intercept all requests going to all the defined methods.

(defined=whatever is on the JpaRepository interface).

so for example when someone calls repo.findAll() I will be able to run a generic code before and after.

(generic=same code of all the entities).

So what I did is created a generic class and implemented methods in JpaRepository and then intercept all the requests.
@Repository
public class BaseJpaRepository<T> implements JpaRepository<T, Long> {

    @Autowired
    private JpaRepository<T, Long> repository;

    @Override
    public List<T> findAll() {
        //run some code here
        List<T> res = repository.findAll();
        //run some code here
        return res;
    }
    // all other methods here...
}

this is the interface to inject into services: 
@Repository
public interface UserRepository extends JpaRepository<UserEntity, Long> {

}

this is the Bean
@Repository
public class UserRepositoryBean extends  BaseJpaRepository<User> implements JpaRepository<User, Long> {

}

The problem is that private JpaRepository<T, Long> repository; is not injecting, I assume that this is because spring needs the Entity type in bootstrap time.
I also tried to inject explicit type it to the constructor if UserRepositoryBean and pass it to the parent.  but its unsatisfied. 
@Repository
public class UserRepositoryBean extends  BaseJpaRepository<User> implements JpaRepository<User, Long> {

public UserRepositoryBean(JpaRepositry<User, Long> repo){super(repo);}

}

Any way to intercept all the Spring jpa methods?
Thanks

A:

First you define basic interface that all your custom repositories will be inherited from
@NoRepositoryBean
interface BaseJpaRepository<T, ID> extends JpaRepository<T, ID> {
     // You can also declare any generic methods here, 
     // and override (intercept) them in BaseJpaRepositoryImpl as well
}

And it's implementation as well
@NoRepositoryBean
class BaseJpaRepositoryImpl<T, ID>
        extends SimpleJpaRepository<T, ID>
        implements BaseJpaRepository<T, ID> {

    public BaseJpaRepositoryImpl(JpaEntityInformation<T, ID> entityInformation, EntityManager em) {
        super(entityInformation, em);
    }

    // One of 'defined' methods inherited from SimpleJpaRepository (and in turn from JpaRepository)
    @Override
    public List<T> findAll() {
        //run some code here
        List<T> res = super.findAll();
        //run some code here
        return res;
    }

    // other 'defined' methods to intercept ...
}

Your custom repository would then look just as usual except that it is now derived from your BaseJpaRepository interface instead of Spring's JpaRepository
@Repository
interface UserRepository extends BaseJpaRepository<User, Long> {
}

To make it all work, let's modify following annotation that is usually placed onto some @Configuration class or onto @SpringBootApplication-ed class
@EnableJpaRepositories(
        basePackages = {"org.example.repositories"},
        repositoryBaseClass = BaseJpaRepositoryImpl.class
)

P.S. Another viable approach is to use Spring AOP. You can also check out similar Question here

