5

我有一个有很多现有代码的 Servlet。我正在尝试将依赖注入添加到其中的一部分。目前我正在手动进行:

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

这里 book 和 offer 存储库依赖项通过构造函数注入到 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
}

现在,您可以在 servlet 中为 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。你如何处理这取决于你的应用程序当前是如何引导的。对于 servlet,我强烈建议您研究Guice-Servlet 扩展,它允许您在“类型安全、惯用的 Java”而不是 web.xml 文件中定义您的 servlet 和依赖项。精美简单。

或者此时使用框架会同样复杂和混乱?

正如您在上面看到的,您可以慢慢开始直接在现有 Web 应用程序中注入绑定(和提供程序),而无需轻松更改接口或调用模式。剩下的就是助推器...只需将 DI 偷偷溜进去,让它慢慢接管 :)

于 2012-10-19T03:04:34.590 回答
0

我不确定我是否正确理解您要执行的操作。这本书是 request 范围的,而 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 回答