Java SE /EE 中的 CDI 除了管理用户会话外还有什么用?

Except for managing user sessions, what are CDI for in Java SE /EE?

我了解 CDI 在 JavaEE Web 应用程序中的作用,它们帮助在 bean 之间传递用户会话数据。 在没有用户会话的情况下,在 Java SE 或 Java EE 应用程序中使用 CDI 是否有充分的理由?

以下是 Java EE CDI 在 JavaSE 应用程序中的一些用例

1 个事件总线

public void someMethod(@Observes @SomeFilter(SomeContext.SOME_FLAG) SomeEvent event) { ....

2 种模式

@Produces
@Dependent
@ChartCanvasResult(DataFlow.CTS_FLOW)
Canvas canvasChart;

@Inject
@ModelResult(SomeContext.SOME_FLAG)
List<Double> someDataSinkList;

@Dependent
@Named("SomeService")
class SomeServiceImpl  implements SomeService {

3 应用程序 bootstrap 上下文

 Weld weld = new Weld();
 WeldSEShutdownHook shutdownHook = new WeldSEShutdownHook(weld);
 Runtime.getRuntime().addShutdownHook(shutdownHook);
 weldContainer = weld.initialize();

4 运行时上下文

   public Object call(Class<?> clazz) {
    log.debug("creating controller= {}", clazz.getSimpleName());

    try {
        return WeldSe.get(clazz);
    } catch (Exception e) {
        log.error("Error creating controller= " + clazz, e);
        throw new RuntimeException(e);
    }
}

上面的 1 到 4 允许我使用企业模式管理 bootstrap、运行时对象图、关闭和布局我的代码。
Weld

大家似乎对CDI是什么有误解。我将解释它是什么,然后介绍一些用例及其优势。


什么是 CDI?

CDI 代表 "Contexts and Dependency Injection"。它是用于依赖注入的 JEE 框架。有关更多信息,请访问 github tutorial of the project. I skip the explanation of dependency injection, the interested reader can look it up, e.g. on wikipedia.


依赖注入有什么好处?

部署依赖注入的主要好处是减少摩擦:通过将依赖注入 class,class 与其依赖分离,并且可以在不更改代码的情况下交换依赖.我在 .

中给出了一个深入的例子

依赖注入还可以带来更简洁的架构:class 定义 REST 端点可注入必要的服务。 return 中的服务注入必要的 repositories/DAOs。三层架构是最典型的,但不一定是only/right形式。但是请记住,架构是

  • a) 活着,即随着项目的发展而改变
  • b) 应该始终与项目团队一起决定或至少讨论的事情。如果团队不喜欢架构,就不会遵循它,从而使其变得无用。
  • c) 主观指标。很少有人会发现一种架构是 最佳架构的情况。大多数时候,这是一个品味问题。

architectures/principles 的主要部分基于依赖注入的示例是 SOLID-principles and hexagonal architecture

减少耦合带来的另一个好处是更好的可测试性。通过注入依赖项的模拟,例如,可以单独测试单个服务。


结束语

能力越大,责任越大。软件工程并不是要将所有事物与其他事物分离。大多数时候,它决定哪里需要解耦,哪里需要耦合。太多的抽象和解耦会导致难以维护的不可读的混乱。举个例子:尽管我很喜欢 CDI 事件,但它们往往会掩盖业务逻辑的实际工作流程,尤其是在多个地方触发和观察事件的情况下。

在技术说明上,应该避免字段注入。 DI 框架必须采用反射以使字段注入可行。仅此一项就应该破坏交易。此外,class 的依赖关系变得模糊。如果添加或删除依赖项,bean 仍将被创建,可能具有 null 值,而另一个 bean 应该是。 setter注入也是如此。这就是为什么构造函数注入被认为是三种方法中最干净的方法。