首页 > 解决方案 > Guice 注入在 Web 应用程序中不起作用

问题描述

我试图让 Guice 在部署在 JBoss EAP 6.4 上的 Web 应用程序中工作 当我尝试单步执行 Guice 代码时,我注意到绑定正在发生。但是,当我尝试注入绑定对象时,我总是得到空值。以下是我为启用 Guice 所做的代码更改 -

1) web.xml

<listener>
    <listener-class>com.univeris.guice.GuiceConfig</listener-class>
</listener>

<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

2)GuiceConfig

@Singleton
public class GuiceConfig extends GuiceServletContextListener {
@Override
protected Injector getInjector() {
    Injector injector = Guice.createInjector(
            new ServletModule() {
                @Override
                protected void configureServlets() {
                    serve("/uif/*").with(UIFInitializeServlet.class);
                    serve("/upm/*").with(IDPServlet.class, ImmutableMap.of("instance-name","upm"));
                    serve("/uiw/*").with(IDPServlet.class, ImmutableMap.of("instance-name","uiw"));
                }
            },
            new MainModule()
    );

    return injector;
  }
}

3)主模块

public class MainModule extends AbstractModule {

    @Override
    protected void configure() {
        install(new BankAccountModule());
        install(new CoreModule());
    }
}

4)银行账户模块

public class BankAccountModule extends AbstractModule {
    @Override
    protected void configure() {
 bind(BankAccountProvider.class).toProvider(BankAccountGuiceProvider.class);      
 bind(BankAccountService.class).toProvider(BankAccountServiceProvider.class);
    }
}

5) BankAccountGuiceProvider

public class BankAccountGuiceProvider implements Provider<BankAccountProvider> {
    @Override
    public BankAccountProvider get() {
        return ProviderLocator.locateProvider(BankAccountProvider.class);
    }
}

6) BankAccountServiceProvider

public class BankAccountServiceProvider implements Provider<BankAccountService> {

    @Override
    public BankAccountService get() {
        BankAccountService bankAccountService = ServiceLocator.locateService(BankAccountService.class);
        return bankAccountService;
    }
} 

7)银行账户服务UVS

@Stateless
@Interceptors(ServiceInterceptor.class)
public class BankAccountServiceUVS implements BankAccountService {

    @Inject
    private BankAccountProvider _bankAccountProvider;

    @Override
    public BankAccountCollection getAllBankAccounts(final Integer entityId, final String entityType) {
        BankAccountCollection retVal = _bankAccountProvider.getAllBankAccounts(entityId, 
        return PojoHelper.cloneObject(retVal);
    }
}

_bankAccountProvider始终作为 null 注入。我已经在几个论坛中倾注了几天,但无济于事。有人可以指出我缺少什么吗?

标签: guice

解决方案


Guice 假设如果您为一个对象编写一个 Provider,那么您已经注入了该对象,并且它本身不需要这样做。

Guice Wiki 的 Injections 页面上,Guice 列出了从图中访问注入对象的方法,但在大多数情况下,Guice 假设它自己创建了这些对象(除了底部的 Automatic Injections 部分,它适用于toInstancetoProvider绑定到已经创建的实例)。

您的 Provider 用于ServiceLocator.locateService查找和创建您的 BankAccountService,这不会触发 Guice 的任何注入。因此,您的 BankAccountService 将不会@Inject注入其 -annotated 成员。


在你的位置上,我会谨慎行事:你已经将 BankAccountServiceUVS 变成了一个显然希望使用依赖注入框架创建的类。您的 ServiceLocator 和 Guice Injector 有一些重叠的职责,如果任何非 Guice 客户要注入您的 BankAccountServiceUVS,他们会将您的 @Inject 字段视为null. 我将继续使用其中一个选项,首先使用我最喜欢的选项:

  • 从 JNDI 中删除 BankAccountServiceUVS 并根据需要使用 Guice 创建并使用拦截器注入它。这恰当地反映了 BankAccountServiceUVS 在没有 Guice、Spring 或其他一些@Inject 感知框架的情况下将无法工作。

  • 修改 BankAccountService 以包含一个初始化方法,例如void init(BankAccountProvider accountProvider). 这意味着 BankAccountService 消费者有调用该方法的额外要求,但允许 BankAccountService 工作,而不管实现或依赖注入框架如何。为了获得 BankAccountProvider,你可以在你的BankAccountServiceProvider类中添加一个 @Inject 字段;与 BankAccountService 不同,BankAccountServiceProvider 由 Guice 创建并自动访问 @Inject 字段

  • 修改 BankAccountServiceProvider 以注入 Injector,这是Guice 中的默认绑定。在调用 中get,从 JNDI 获取您的 BankAccountService 后,调用Injector.injectMembers(Object)它。这将通过反射检查对象实例来填充所有@Inject字段并调用所有@Inject方法。请注意,这是这三种方法中最不直观和最危险的,因为 Guice 检查对象的动态类型(BankAccountServiceUVS),而其他 DI 框架(如 Dagger)只会检查对象的静态类型(BankAccountService)而不会找到任何东西@Inject-annotated 在界面上。它还有效地要求使用像 Guice 这样的 DI 框架构建 BankAccountServiceUVS,因为调用new BankAccountServiceUVS()将成功但与_bankAccountProvider如果 Guice 不注入对象,将会失败。


推荐阅读