java - 将 google guice 应用到方法依赖项

标签 java guice

考虑以下 servlet 代码:

public class AddDevice extends JsonServlet {
    private static final long serialVersionUID = 1L;

    @Override
    protected void doGet(final JsonServletRequest request,
            final JsonServletResponse response) throws ServletException,
            IOException {
        try {
            final DeviceEntity device = new DeviceEntity();

            device.type =
                    FleetManagerDatabaseHelper
                            .deviceTypesAccessor()
                            .queryForId(Integer.valueOf(
                                    request.getParameter(DeviceTypeEntity._ID)));

            device.sn = request.getParameter(DeviceEntity._SN);
            device.status = Long.valueOf(0);

            FleetManagerDatabaseHelper.devicesAccessor().create(device);
        }
        catch (final SQLException e) {
            throw new ServletException("device already exists");
        }
    }
}

此代码取决于 DeviceEntity 和 FleetManagerDatabaseHelper 类。 现在,我想为其编写一个测试,检查创建的实体是否填充了正确的类型、sn 和状态值。 为此,我可以创建一个 FleetManagerDatabaseHelperMockup 类。

您将如何在此处应用 Google Guice(或其他东西)并进行最小的更改?

最佳答案

您的第一步是设计依赖注入(inject) - 避免构造函数和静态方法,而是采用您需要的实例。看起来这些类型是 Provider<DeviceEntity> , DevicesAccessor ,和DeviceTypesAccessor .

Providera very simple Guice interface通过单个无参数方法提供其类型参数中的任何类的实例 get() 。如果您已绑定(bind)Foo ,Guice 自动知道如何绑定(bind) Provider<Foo> 。如果您的实例价格昂贵,或者您在 servlet 的生命周期内需要多个实例(就像您所做的那样),那么它就非常有用。

重构依赖注入(inject)后,您的类将如下所示:

public class AddDevice extends JsonServlet {
  private static final long serialVersionUID = 1L;

  private final Provider<DeviceEntity> deviceEntityProvider;
  private final DevicesAccessor devicesAccessor;
  private final DeviceTypesAccessor deviceTypesAccessor;

  @Inject
  public AddDevice(Provider<DeviceEntity> deviceEntityProvider,
      DevicesAccessor devicesAccessor,
      DeviceTypesAccessor deviceTypesAccessor>) {
    this.deviceEntityProvider = deviceEntityProvider;
    this.devicesAccessor = devicesAccessor;
    this.deviceTypesAccessor = deviceTypesAccessor;
  }

  @Override
  protected void doGet(final JsonServletRequest request,
      final JsonServletResponse response) throws ServletException,
      IOException {
    try {
      final DeviceEntity device = deviceEntityProvider.get();

      device.type = deviceTypesAccessor.queryForId(
          Integer.valueOf(request.getParameter(DeviceTypeEntity._ID)));
      device.sn = request.getParameter(DeviceEntity._SN)
      device.status = Long.valueOf(0);

      devicesAccessor.create(device);
    } catch (final SQLException e) {
      throw new ServletException("device already exists");
    }
  }
}

此时,通过传入一个跟踪其返回实例的 Provider 以及一个模拟 DevicesAccessor 和一个模拟 DeviceTypesAccessor 来编写测试非常容易。 (我推荐 Mockito 。)如果您编写自己的 Provider 接口(interface)并删除 @Inject ,你甚至不需要使用Guice;在您的测试中,您可以继续使用该构造函数,但您希望使用如下构造函数来满足 Java EE 的要求:

public AddDevice() {
  this(new NewDeviceEntityProvider(),
      FleetManagerDatabaseHelper.deviceTypesAccessor(),
      FleetManagerDatabaseHelper.devicesAccessor());
}

private class NewDeviceEntityProvider implements Provider<DeviceEntity> {
  @Override public DeviceEntity get() {
    return new DeviceEntity();
  }
}

但是如果您确实想使用 Guice 删除该样板,只需编写 Guice Module 。您的模块需要将 DeviceTypesAccessor 和 DevicesAccessor 绑定(bind)到 FleetManagerDatabaseHelper 将返回的实例; Guice 会看到 DeviceEntity有一个无参数构造函数,并且能够注入(inject) DeviceEntityProvider<DeviceEntity>自动地。 (如果您希望我详细介绍 Module 的外观,请发表评论。)

希望这有帮助!

关于java - 将 google guice 应用到方法依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12742099/

相关文章:

java - 使用 Guice 将参数传递给构造函数

java - JLabel.setText() 中的换行符

java - 使用套接字读取 .accept() 时,我的服务器停止工作

java - Hibernate 多对一更新外键为空

java - 当 tomcat 服务器运行时,然后我的 java 类运行

java - 未在 App Engine 上调用 Servlet 过滤器

java - 找到 APK : LICENSE when deploying to my phone 的重复文件

java - 如何将JAVA中的x509证书的公钥转换为十六进制

multithreading - 多线程中的 Guice 和 RequestScoped 行为

java - 如何在 guice 提供程序中获取绑定(bind)目标?