2009-06-04 20 views
8

我是Guice的新手,我正在使用大量遗留代码处理应用程序。它有几个类,如下所示:迁移应用程序以使用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在事务更改时注入另一个事务实例? 请注意,交易实例不是很好的支持JPA /休眠/ Spring的事务中的一个

最小侵入性的方法我能想到的(避免一次使用事务需要迁移的每级)只有在实例化对象时才会使用Guice来注入事务,并且我会保留现有的应用程序代码,以便在必要时更新事务。例如,这提供可用于有交易的当前实例注入新的对象:

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(); 
    } 

还有没有其他的方法来更新实例现有类使用的事务而不必一次迁移每个类?

回答

6

如果我理解正确的这个,你的问题有两个独立的部分:

  1. 使用使用遗留类权交易实例吉斯 - 田间类
  2. 正确的交易实例。

对于'1',您的自定义提供程序工作,但我会为事务创建自定义作用域并绑定该范围内的Transaction类。有关自定义范围的说明,请参阅http://code.google.com/p/google-guice/wiki/CustomScopes

关于'2',一旦你有一个自定义范围,这是使用Guice向传统类提供实例的常见问题。您没有提及当前为旧类提供Transaction实例的代码,但您可以更改该特定代码段以从Guice请求实例。由于您处于您的“交易范围”内,因此Guice负责提供正确的实例。

+0

谢谢 - 这看起来像它会起作用。重构遗留类以请求Guice的事务的好处 - 它看起来只是对每个遗留类的小改动,而且它可能比使用2个系统来管理事务更容易。 – 2009-06-08 15:17:46

1

看看Assisted Inject。要使用它,定义一个三线接口:

public interface DataAccessClassFactory { 
    DataAccessClass create(Transaction transaction); 
} 

...然后使用FactoryProvider绑定到工厂绑定:

bind(DataAccessClassFactory.class).toProvider(
    FactoryProvider.newFactory(DataAccessClassFactory.class, DataAccessClass.class)); 

那么无论你需要构建你可以注入一个DataAccessClassFactory一个DataAccessClass。 AssistedInject包含在Guice 2中,但它需要单独的.jar文件。

+0

这看起来可能有帮助,但我没有关注如何使用它来更新事务与表示当前打开的事务的实例的绑定。换句话说:在任何给定时间只使用一个事务实例,但每次启动新事务时都会替换该实例。 有没有更详细的使用AssistedInject的例子?在wiki页面上,我很难找出Date和Money的实例在哪里实例化。 – 2009-06-05 14:45:59

相关问题