为什么在Java EE中使用CDI

Phi*_*Din 49 java spring java-ee cdi

我知道有很多文章解释了如何在Java EE中使用CDI,但我无法弄清楚它实际带来了什么优势.例如,假设我有一个当前使用Foo实例的类.我也许会这样做

Foo myFoo = new Foo();
Run Code Online (Sandbox Code Playgroud)

要么

// Better, FooFactory might return a mock object for testing    
Foo myFoo = FooFactory.getFoo();
Run Code Online (Sandbox Code Playgroud)

我一直在读CDI,我可以这样做:

@Inject
Foo myFoo;
Run Code Online (Sandbox Code Playgroud)

但为什么这比以前的工厂方法更好?我假设还有一些其他用例,我不知道,但我无法识别这一点.

如果我理解了下面的响应,那么概念就是DI框架充当集中配置的主对象工厂.这是一个合理的解释吗?

更新

我从那时起开始学习Spring,现在这更有意义了.下面的段落取自Spring in Practice,以一个AccountService类为例,该类反过来使用了一个实例AccountDao.我为长篇报道道歉,但我认为它真正解释了为什么注入资源提供了超过标准初始化的东西.

您可以使用new关键字构造AccountService,但是服务层对象的创建很少是如此简单.它们通常依赖于DAO,邮件发件人,SOAP代理等等.您可以在AccountService构造函数中(或通过静态初始化)以编程方式实例化每个依赖项,但这会导致硬件依赖性和级联更改,因为它们已被换出.

此外,您可以在外部创建依赖项,并通过setter方法或构造函数参数在AccountService上设置它们.这样做可以消除硬内部依赖关系(只要它们通过接口在AccountService中声明),但是你到处都有重复的初始化代码.以下是如何创建DAO并以Spring方式将其连接到AccountService:

<bean id="accountDao" class="com.springinpractice.ch01.dao.jdbc.JdbcAccountDao"/>

<bean id="accountService"
    class="com.springinpractice.ch01.service.AccountService">
    <property name="accountDao" ref="accountDao"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

如上所述配置bean后,您的程序现在可以AccountService从Spring ApplicationContext 请求一个实例,Spring DI框架将实例化需要实例化的所有内容.

duf*_*ymo 47

写CDI的人给了你一个大对象工厂; 他们为你做了比你更好的工作.它是XML配置或注释驱动的,因此您不必将所有内容嵌入代码中.

像Spring这样的依赖注入引擎比你的工厂做得更多.它将需要多个工厂类和一行代码来复制它们提供的所有内容.

当然你不必使用它.你总是可以自由发明自己的车轮.你应该 - 如果你的目的是学习如何制造轮子或消除依赖性.

但是,如果您只想开发应用程序,最好使用其他人提供的工具,当它们为您提供优势时.

关于依赖注入的开创性文章由Martin Fowler撰写.我建议阅读它; 八年后,它仍然很棒.

"还不清楚是什么"

以下是一些优点:

  1. 松耦合
  2. 更容易测试
  3. 更好的分层
  4. 基于接口的设计
  5. 动态代理(segue to AOP).

  • 不要忘记与Bean Validation,拦截器,轻量级事件和可移植扩展集成(这几乎可以让您构建Java EE中不需要的任何东西). (2认同)
  • 关于车轮发明的伟大文章+1 (2认同)

Nat*_*hes 17

使用依赖注入的目的是使用注入的东西的代码不依赖于工厂.使用您的工厂代码示例,您的代码中嵌入了静态方法调用,而DI方法则不需要这样.

注入的东西myFoo不应该知道工厂.


jor*_*npg 5

这是一个关于企业编程的重要而微妙的问题.

这个名字选择得很好:上下文和依赖项.

CDI与更好或更清晰的代码无关,而是确保大型组织可以构建复杂的分布式软件系统并共享数据.这是关于100%确保政府或其他官僚机构可以不加选择地为他们控制的每一个软件分发自包含,记录良好的软件包.请记住,现在几乎可以注入任何POJO.

假设您正在构建某种类型的客户端应用程序,并且您希望它在角落中打印用户的第一个名称.

  • 这家大公司的企业架构师希望您具备此功能,但作为初级软件工程师,您不可能将密钥交给数据库.

  • 他们还希望通过网络保护数据,但公司并不需要任何工程师在每次需要共享数据时重新设计身份验证客户端.

  • 他们希望您能够查询和更新此信息,但希望事务处理的级别高于任何一个应用程序.

  • 他们希望您能够在设置块中使用琐碎的模拟测试您的类.

  • 他们希望类之间的耦合涉及最少的静态方法.

  • 并且一直在......

大多数JSR可能都有"EAs希望能够......"埋藏在某个地方.

CDI是首选,因为它允许大(任意?)水平和垂直比例的应用程序共享上下文,依赖项,因此共享数据.

用福勒的话来说:

"问题是我如何建立这个链接,以便我的lister类不知道实现类,但仍然可以与实例通信来完成它的工作."

"但是如果我们希望以不同的方式部署这个系统,我们需要使用插件来处理与这些服务的交互,这样我们就可以在不同的部署中使用不同的实现."

"这些容器使用的方法是确保插件的任何用户遵循一些允许单独的汇编程序模块将实现注入列表器的约定."

简而言之,它们允许对复杂的企业应用程序进行集中的"命令和控制". Java EE是一个系统化,可靠的抽象过程,而CDI是它的化身,它运作良好,几乎使它看不见.它使复杂应用程序的拼接几乎是微不足道的.

还有两件事:

  1. 请注意,CDI与"服务定位器模式"(Java EE中称为JNDI)并行存在,如果客户端开发人员需要在许多相同类型的替代方案中进行选择,则更为可取.

  2. CDI比许多情况下需要的火力更强,特别是非企业(字面意思)的情况.