'Defining a custom TransactionInterceptor in Spring. And why/how bean overridding works?

What I want to achieve

My objective is to have a transactional bean, instantiated twice (or more), and each time w/ a different TransactionManager (i.e. a different DB).

@Transactional
class MyReusableService {
...
}

@Configuration
class MyConfig {

  // here I want to use `transactionManagerForDb1`
  @Bean
  public MyReusableService myReusableServiceForDb1() { ... }

  // here I want to use `transactionManagerForDb2`
  @Bean
  public MyReusableService myReusableServiceForDb2() { ... }
}

What I observed

TransactionInterceptor is the piece that delegates to a TransactionManager (TM). I found it used in 2 ways:

  1. Via @EnableJpaRepositories(... transactionManagerRef="..."). This mechanism relates a bit w/ what I want. But it doesn't use @Transactional at all. It finds all the repos. And it instantiates one TransactionInterceptor per repo.

  2. Via @Transactional. Here, there is a single instance of TransactionInterceptor (TI). And at each invocation, it decides which TM to use by looking at the annotations (using caching of course). This TI is defined ProxyTransactionManagementConfiguration.

What I did

I defined my own TI:

@Configuration
public class MyConfiguration {

    @SuppressWarnings("serial")
    public static class MyTransactionInterceptor extends TransactionInterceptor {
        ...
    }
    
    @Bean
    public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
        TransactionInterceptor interceptor = new MyTransactionInterceptor();
        interceptor.setTransactionAttributeSource(transactionAttributeSource);
        return interceptor;
    }
    
}

This seem to work. The TI defined by Spring is no more instantiated. Mine is. And it is used.

My questions

  1. Why does the above work? How did Spring know that I wanted to override it's TI? I was expecting to have 2 TIs, and fight to use the right one, maybe using @Primary. E.g. like here.
  2. Is there maybe a cleaner way to achieve my objective? I cannot say I'm entirely satisfied, because I find the solution a bit intrusive. MyReusableService resides actually in a lib. And forcing the user to override the TI is not self contained.


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source