Carl Papa 在 Spring 框架中使用方面来确定要使用的 DataSource
(读写或只读),这启发了我。所以,我正在写这篇文章。
我必须承认,我早就熟悉 Spring 的 AbstractRoutingDataSource
。但是我不知道在哪里可以使用它。感谢 Carl 和团队,以及他们的一个项目。现在,我知道一个很好的用例。
使用 Spring,只读事务通常用注释标记。
public class ... { @Transactional(readOnly=true) public void ...() {...} @Transactional // read-write public void ...() {...} }
为了利用这一点,我们使用 Spring 的 TransactionSynchronizationManager
来确定当前事务是否是只读的。
在这里,如果当前事务是只读的,我们使用 Spring 的 AbstractRoutingDataSource
路由到只读副本。否则,它会路由到默认主机。
public class ... extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { if (TransactionSynchronizationManager .isCurrentTransactionReadOnly() ...) { // return key to a replica } return null; // use default } ... }
使用上述方法后,我们发现 TransactionSynchronizationManager
落后了一步,因为在建立同步之前 Spring 已经调用了 DataSource.getConnection()
。因此,还需要配置 LazyConnectionDataSourceProxy
。
在讨论这个问题时,我们想知道是否有另一种方法可以确定当前事务是否是只读的(无需求助于 LazyConnectionDataSourceProxy
)。因此,我们提出了一种实验性方法,其中一个方面捕获 TransactionDefinition
(来自 @Transactional
注释,如果有的话)作为线程局部变量,以及一个 AbstractRoutingDataSource
根据捕获的信息进行路由。
相关源码可以在GitHub上找到。再次感谢 Carl!顺便说一句,Carl 也是一位屡获殊荣的电影导演。哇,人才绝对是无国界的。
地址:https://www.cundage.com/article/jcg-datasource-routing-spring-transactional.html