Migration Anwendung Guice zu verwenden - wie Transaktionen in bestehende Objekte zu injizieren?

StackOverflow https://stackoverflow.com/questions/951831

  •  11-09-2019
  •  | 
  •  

Frage

Ich bin neu in Guice, und ich arbeite es in eine Anwendung mit einer großen Menge von Legacy-Code. Es hat mehrere Klassen, die wie folgt aussehen:

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'
    }
}

Es ist ziemlich klar, wie Guice verwenden Instanzen zu binden, die sich nie ändern, aber was Instanzen, die Veränderung zu tun (das heißt Transaktionen)? Gibt es eine Möglichkeit für mich Guice zu verwenden, um eine andere Instanz von Transaktion zu injizieren, wenn sie sich ändert? Beachten Sie, dass die Transaktion Instanz nicht einer der gut unterstützten JPA / Hibernate / Frühjahr Transaktionen

Die am wenigsten invasive Ansatz, den ich mich vorstellen kann (die Notwendigkeit vermieden wird jede Klasse zu migrieren, die eine Transaktion auf einmal verwendet) würde Guice verwenden Transaktion nur zu injizieren, wenn Objekte instanziieren, und ich würde den bestehenden Anwendungscode halte, dass Updates Transaktionen, wenn notwendig. Zum Beispiel könnten dies Provider verwendet werden, um neue Objekte mit der aktuellen Instanz von Transaktion zu injizieren:

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

Anwendungslogik würde wie folgt aussehen:

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

Gibt es andere Möglichkeiten, um die Instanz von Transaktion zu aktualisieren, die vorhandenen Klassen zu benutzen, ohne jede Klasse auf einmal zu migrieren?

War es hilfreich?

Lösung

Wenn ich das richtig verstehen, Ihr Problem hat zwei unabhängige Teile:

  1. mit der rechten Transaktion Instanz auf Guice-fied Klassen
  2. mit der rechten Transaktion Instanz auf Legacy-Klassen.

‚1‘, Ihre benutzerdefinierten Anbieter funktioniert, aber ich würde einen benutzerdefinierten Rahmen für eine Transaktion und binden, um die Transaktionsklasse in diesem Bereich erstellen. Siehe http://code.google.com/p/google-guice/wiki / CustomScopes für Anweisungen über benutzerdefinierte Bereiche.

In Bezug auf ‚2‘, sobald Sie einen benutzerdefinierten Bereich haben, ist dies das übliche Problem von Guice mit Instanzen auf Legacy-Klassen zur Verfügung zu stellen. Sie haben den Code nicht erwähnen, die zur Zeit der Transaktion Instanzen auf Legacy-Klassen bieten, aber man konnte nur dieses bestimmte Stück Code ändern, um eine Instanz von Guice zu beantragen. Da Sie in Ihrem „Transaktionsbereich“ sind, nimmt Guice Pflege die richtige Instanz bereitstellt.

Andere Tipps

Hier finden Sie aktuelle Assisted Inject . Um es zu nutzen, definieren eine dreizeilige Schnittstelle:

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

... und dann mit einem FactoryProvider Bindung, die Fabrik zu binden:

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

Dann können Sie eine DataAccessClassFactory injizieren, wo immer Sie eine DataAccessClass konstruieren müssen. AssistedInject ist in Guice 2 enthalten, obwohl es eine separate .jar-Datei erfordert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top