迁移应用程序以使用 Guice - 如何将事务注入现有对象?
-
11-09-2019 - |
题
我是 Guice 的新手,我正在将其应用到具有大量遗留代码的应用程序中。它有几个类似这样的类:
public final class DataAccessClass {
private Transaction txn;
@Inject //This was just added
public DataAccessClass(/* injectable parameters */, Transaction txn) {
this.txn = txn;
}
//Maybe add @Inject here to set a new transaction when it changes?
public void setTransaction(Transaction txn) {
this.txn = txn;
}
public void writeData(/* parameters for data to be written */) {
//Write data using the current instance of 'txn'
}
}
如何使用 Guice 绑定永不改变的实例是非常清楚的,但是对于发生改变的实例(即交易)?有没有办法让我在 Transaction 发生变化时使用 Guice 注入不同的 Transaction 实例? 请注意,Transaction 实例不是受良好支持的 JPA/Hibernate/Spring 事务之一
我能想到的侵入性最小的方法(避免一次迁移每个使用事务的类)将仅在实例化对象时使用 Guice 注入 Transaction,并且我会保留在必要时更新事务的现有应用程序代码。例如,此 Provider 可用于通过当前 Transaction 实例注入新对象:
public final class TransactionProvider implements Provider<Transaction> {
/** Nullable transaction that should be used for all operations at the moment */
private Transaction txn;
public TransactionProvider(Transaction txn) {
this.txn = txn;
}
/**
* @param txn Nullable transaction to use for all operations at the moment
*/
public void setTransaction(Transaction txn) {
this.txn = txn;
}
/* Provider methods */
public Transaction get() {
return this.txn;
}
}
应用程序逻辑看起来像这样:
public final class Application {
private final Provider<Transaction> transactionProvider;
private final DataAccessClass dao; //Instance provided by Guice
public void scopedOperation() {
//Use a fresh transaction for this operation
final Transaction txn = ...;
//Make transaction available to Guice (for new objects) and to legacy (already-instantiated) DAO classes
this.transactionProvider.setTransaction(txn);
this.dao.setTransaction(txn); //Legacy approach - can this be updated?
//Do some kind of data operation under the scope of the current transaction
try {
this.dao.writeData(...);
} catch (Exception e) {
txn.abort();
throw new RuntimeException("Operation failed", e);
}
//The operation is over now
this.txn.commit();
}
是否有其他方法可以更新现有类使用的 Transaction 实例,而不必立即迁移每个类?
解决方案
如果我理解正确的话,你的问题有两个独立的部分:
- 在 Guice-fied 类上使用正确的 Transaction 实例
- 在遗留类上使用正确的 Transaction 实例。
对于“1”,您的自定义提供程序可以工作,但我会为事务创建自定义范围并在该范围绑定 Transaction 类。看 http://code.google.com/p/google-guice/wiki/CustomScopes 有关自定义范围的说明。
关于“2”,一旦您拥有自定义范围,这就是使用 Guice 向遗留类提供实例的常见问题。您没有提到当前向遗留类提供 Transaction 实例的代码,但您可以更改该特定代码段以从 Guice 请求实例。由于您位于“事务范围”内,Guice 会负责提供正确的实例。
其他提示
看一看辅助进样。要使用它,定义一个三线接口:
public interface DataAccessClassFactory {
DataAccessClass create(Transaction transaction);
}
...,然后使用FactoryProvider
结合到工厂结合:
bind(DataAccessClassFactory.class).toProvider(
FactoryProvider.newFactory(DataAccessClassFactory.class, DataAccessClass.class));
然后在任何需要构造一个DataAccessClassFactory
你可以注入一个DataAccessClass
。 AssistedInject被包括在吉斯2,尽管它需要单独的.jar文件。