【问题标题】:Java EE dependency Injection when to use?Java EE依赖注入什么时候用?
【发布时间】:2013-12-29 15:21:43
【问题描述】:

我是新手,我想了解什么时候在 Java 中使用 DI 是合适的。假设我需要用不同的 ping 参数 ping 不同的网络:

PingParams 类:

public class PingParams {
int timeout;
int retries;
}

PingResult 类:

public class PingResult {
int ttl;
boolean available;
}

PingService 类:

public class PingService {

private PingParams pingParams;

@Inject
public PingService(PingParams pingParams) {
    this.pingParams = pingParams;
}

public PingResult ping(String ip) {
    // ping using timeout and retries from pingParams
    return new PingResult();
}
}

客户:

public class Client {

@Inject
PingService pingService;

private List<PingResult> doPing() {
    List<PingResult> ret = new ArrayList<>();
    String[] ips = new String[] {"127.0.0.1","127.0.0.2"};
    for (String ip : ips) {
        PingResult pr = pingService.ping(ip);
        ret.add(pr);
    }
    return ret;
}

public static void main(String[] args) {
    List<PingResult> prs = new Client().doPing();
    System.out.println(prs);
}
}

我有 2 个注入点:

  1. 我在 PingService 的构造函数中注入了 PingParams。

这是正确的吗?我的意思是,除非您创建一些“Produces”注释方法,否则 DI 容器无法知道超时并重试注入 PingParams,即使在这种情况下,它也需要大量工作来创建对象!但是当然你需要为每个网络创建几个,你如何使用 DI 来做到这一点?

  1. 我在客户端注入 PingService。

看起来是合法的,但 PingService 依赖于 PingParams,它会将我们带到 1 号注入点。

在我看来,使用 DI 的唯一合适方法是使用没有依赖项(因此无用)的类,或者使用非常简单的服务类,您可以将所有依赖项作为参数传递给服务方法。例如,在 ping 方法中接受 ip 和 PingParams 的 PingService,同样,这个类将没有依赖关系......

我错过了什么吗?您如何将 DI 与这些“数据”类一起使用,这些类仅包含用于保存数据的字段 (PingParams)?在这些情况下是否应该避免 DI?谢谢

【问题讨论】:

    标签: java jakarta-ee dependency-injection cdi weld


    【解决方案1】:

    一般来说,您应该只对非数据类使用依赖注入。如果您的课程同时包含数据和非数据协作者,您可以使用assisted injection

    您所说的 ping 参数确实应该在您的应用程序启动时绑定到一个实例,并在必要时注入。对于您的示例,这确实是很多代码,但从长远来看,它可以在更大的项目中保持整洁。

    总结一下:在应用程序启动时绑定 PingParam(例如作为 Singleton),将其注入 PingService,并在没有 DI 的情况下创建 PingResult(就像您所做的那样)。

    关于依赖注入的最佳实践,我推荐阅读Dependency Injection by Prasanna

    【讨论】:

    • 非常感谢。我不知道您是否看到过:“我需要使用不同的 ping 参数 ping 不同的网络”问题可能是我的问题,因为它没有被举例说明。我想说的是,我需要有几个“PingParams”实例,每个我试图 ping 的网络都有一个实例,那么如何创建这些实例呢?如果没有 DI,这很容易,只需创建 PingParams 实例并将它们传递给 PingService 的构造函数,同样无需使用 DI。使用 DI?我不知道怎么做:)
    • Guice 很不错,但在 JavaEE 中有 Weld,这是完全不同的。
    • 我不知道焊接。在 Guice 中,如果您命名/了解网络,它将使用 Named bindings。例如,您可以注入 @NetworkA PingParams params。否则,如果网络列表是动态的,我将使用Multibindings 添加任意数量的网络。
    【解决方案2】:

    假设我们谈论的是 CDI/Weld。假设您的 PingParams 类存储在数据库中,作为从某个表加载的配置。将其抽象出来会很有意义,只需为PingParams 类提供一个生产者方法,该方法从数据库中读取数据并返回此数据元素。为此配置使用数据对象并为其提供生产者并不是一个坏主意。

    【讨论】:

    • 谢谢约翰,我还不清楚我从哪里得到这些 PingParams,我只知道它们各不相同。我也不太明白如何让这个方法在正确的时间被调用,对于一个 IP,因为你不控制使用 new 的创建。我得调查一下。
    猜你喜欢
    • 2012-11-11
    • 1970-01-01
    • 2014-11-23
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多