5

多くの既存のコードを持つサーブレットがあります。その一部に依存性注入を追加しようとしています。現在、私は手動でやっています:

public class AdjustBookPriceHandler extends BookRequestHandler {
    @Override
    public void handleRequest(RequestState requestState, RequestData requestData, Object obj) {
        Book book = (Book) obj;
        long newPrice = Long.parseLong(requestData.getQueryParam("price");
        OfferRepository offerRepository = ((BookData) requestState.getData()).getOfferRepository();

        BookPriceAdjuster priceAdjuster = getBookPriceAdjuster();
        priceAdjuster.adjustPrice(newPrice);
    }

    protected BookPriceAdjuster getBookPriceAdjuster(RequestState requestState, RequestData requestData, Book book) {
        return new BookPriceAdjuster(book, offerRepository);
    }
}

ここでは、本とオファーのリポジトリの依存関係が、コンストラクターを介して BookPriceAdjuster に注入されます。getBookPriceAdjuster メソッドは、AdjustBookPriceHandler から継承するクラスが別の価格調整機能を提供できるようにするために存在します。

Guice のような DI フレームワークの使用を開始して、複雑な例で導入されるボイラープレート コードの一部を削減したいと考えています。ただし、このコンテキストでそれを使用する最善の方法はわかりません。

「神」オブジェクト RequestState および RequestData から関連する依存関係を引き出すバインディングを作成するにはどうすればよいですか? それとも、この時点でフレームワークを使用することは、同じように複雑で厄介でしょうか?

4

2 に答える 2

0

「神」オブジェクトRequestStateおよびRequestDataから関連する依存関係を引き出すバインディングを作成するにはどうすればよいですか?

アプリケーションのブートストラップ方法によっては、ここで依存性注入にGuiceをかなり簡単に使用できるようになります。BooksModuleがあるとしましょう。

public class BooksModule extends AbstractModule {
    protected void configure() {
        // Do Nothing
    }

    @Provides @RequestScoped
    BookData provideBookData(RequestState requestState) {
      return (BookData) requestState.getData();
    }

    @Provides @RequestScoped
    OfferRepository provideOfferRepository(BookData bookData) {
      return bookData.getOfferRepository();
    }
}

これで、Guiceを使用して依存関係をBookPriceAdjusterクラスに挿入できます。

@RequestScoped
public class BookPriceAdjuster {
    private final Book book;
    private final OfferRepository offerRepository;

    @Injected
    public BookPriceAdjuster(Book book, OfferRepository offerRepository) {
        this.book = book;
        this.offerRepository = offerRepository;
    }

    // whatever methods it has
}

これで、サーブレット内でBookPriceAdjusterのプロバイダーを使用できます。

public class AdjustBookPriceHandler extends BookRequestHandler {

    private final Provider<BookPriceAdjuster> bookPriceAdjusterProvider;

    @Injected
    public AdjustBookPriceHandler(Provider<BookPriceAdjuster> bookPriceAdjusterProvider) {
        this.bookPriceAdjusterProvider = bookPriceAdjusterProvider;
    }

    @Override
    public void handleRequest(RequestState requestState, RequestData requestData, Object obj) {
        Book book = (Book) obj;
        long newPrice = Long.parseLong(requestData.getQueryParam("price");

        BookPriceAdjuster priceAdjuster = bookPriceAdjusterProvider.get();
        priceAdjuster.adjustPrice(newPrice);
    }
}

アプリケーションをブートストラップするには、Guiceインジェクターを使用してBooksModuleをインストールする必要があります。これをどのように行うかは、アプリケーションが現在どのようにブートストラップされているかによって異なります。サーブレットの場合、web.xmlファイルではなく「タイプセーフで慣用的なJava」でサーブレットと依存関係を定義できるGuice-Servlet拡張機能を調べることを強くお勧めします。美しくシンプル。

または、この時点で、フレームワークの使用は同じように複雑で面倒ですか?

上記のように、インターフェースを変更したりパターンを呼び出したりすることなく、既存のWebアプリ内にバインディング(およびプロバイダー)をゆっくりと注入し始めることができます。残っているのはブートストラップだけです...そこにDIをこっそり入れて、ゆっくりと引き継いでください:)

于 2012-10-19T03:04:34.590 に答える
0

あなたがやろうとしていることを正しく理解しているかどうかはわかりません。本はリクエストスコープで、offerRepository はシングルトンスコープですか? もしそうなら、あなたはこのようなことをすることができます..

public class AdjustBookPriceHandler extends BookRequestHandler {

    // inject concrete instance with setter or constructor
    private BookPriceAdjusterProvider bookPriceAdjusterProvider;

    @Override
    public void handleRequest(RequestState requestState, RequestData requestData, Object obj) {
        Book book = (Book) obj;
        long newPrice = Long.parseLong(requestData.getQueryParam("price");

        BookPriceAdjuster priceAdjuster = bookPriceAdjusterProvider.getBookPriceAdjuster(book);
        priceAdjuster.adjustPrice(newPrice);
    }

}

public interface BookPriceAdjusterProvider {

    BookPriceAdjuster getBookPriceAdjuster(Book book);

}

public class MyBookPriceAdjusterProvider {

    // inject this through setter or constructor
    private OfferRepository offerRepository;

    protected BookPriceAdjuster getBookPriceAdjuster(Book book) {
        return new BookPriceAdjuster(book, offerRepository);
    }
}

このようにして、シングルトン スコープの OfferRepository を取り除き、DI フレームワークを使用してインジェクションを行うことができます。サブクラスなどで必要に応じて、BookPriceAdjusterProvider の別の実装を使用することもできます。これはあなたが望んでいたことですか、それとも私はあなたの目的を完全に誤解していますか?

于 2011-09-14T16:11:03.983 に答える