java - Java依赖注入(inject): XML or annotations

标签 java spring dependency-injection guice cdi

注释变得流行。 Spring-3支持它们。 CDI严重依赖于它们(我不能在没有注解的情况下使用CDI,对吗?)

我的问题是为什么?

我听到了几个问题:

  • “它有助于摆脱XML”。但是xml有什么不好呢?依赖关系本质上是声明性的,而XML对于声明非常有用(对于命令式编程则非常不利)。
    使用良好的IDE(例如想法),可以很容易地编辑和验证xml,不是吗?
  • “在许多情况下,每个接口(interface)只有一个实现”。那是不对的!
    我系统中的几乎所有接口(interface)都具有用于测试的模拟实现。

  • 还有其他问题吗?

    现在,我对XML的优点:
  • 您可以在任何地方注入(inject)任何东西(不仅是带有注释的代码)
  • 如果一个接口(interface)有多个实现,该怎么办?使用限定词?但这迫使我的类知道它需要哪种注入(inject)。
    这对设计不利。

  • 基于XML的DI使我的代码清晰明了:每个类都不了解注入(inject),因此我可以用任何方式对其进行配置和单元测试。

    你有什么感想?

    最佳答案

    我只能从与Guice的经验谈起,但这是我的看法。缺点是基于注释的配置极大地减少了将应用程序连接在一起所需的编写工作量,并使更改依赖于内容的内容变得更加容易...通常甚至都无需触摸配置文件本身。它通过使最常见的案例变得绝对琐碎来做到这一点,但要以使某些相对罕见的案例更难处理为代价。

    我认为让类(class)过于“教条化”是个问题。在类代码中不应引用注入(inject)容器。我完全同意。但是,我们必须清楚一点:注解不是代码。就它们自己而言,它们对类的行为没有任何改变……您仍然可以创建带有注释的类实例,就像它们根本不存在一样。因此,您可以完全停止使用DI容器,而将注释保留在那里,并且不会有任何问题。

    当您选择不提供有关类中注入(inject)的元数据提示(即注释)时,您将丢掉有关该类所需依赖项的有值(value)的信息源。您被迫在其他地方(例如XML)重复该信息,或者依赖诸如 Autowiring 之类的不可靠魔术,这可能会导致意外问题。

    要解决您的一些特定问题:

    它有助于摆脱XML

    XML配置有很多不好的地方。

  • 太冗长了。
  • 如果没有特殊工具,它不是类型安全的。
  • 它要求使用字符串标识符。同样,没有特殊工具的支持也不安全。
  • 不利用语言的功能,需要各种丑陋的结构来完成使用简单的代码方法即可完成的工作。

  • 就是说,我知道很多人已经使用XML足够长时间了,以至于他们确信XML很好,而且我真的不希望改变主意。

    在许多情况下,每个接口(interface)只有一个实现

    对于应用程序的单个配置(例如生产),每个接口(interface)通常只有一个实现。关键是,启动应用程序时,通常只需要将接口(interface)绑定(bind)到单个实现即可。然后可以在许多其他组件中使用它。使用XML配置时,您必须告诉使用该接口(interface)的每个组件都使用该接口(interface)的这种特定绑定(bind)(如果需要,可以使用“bean”)。使用基于注释的配置,您只需声明一次绑定(bind),其他所有内容都会自动处理。这非常重要,并且大大减少了您必须编写的配置量。这也意味着,当您向组件添加新的依赖项时,您通常根本不需要更改任何配置!

    您具有某个接口(interface)的模拟实现是无关紧要的。在单元测试中,您通常只创建模拟并自己传递模拟……它与配置无关。如果您使用模拟程序为具有某些接口(interface)的集成测试设置了完整的系统...则不会有任何改变。对于系统的集成测试运行,您仍然仅使用一种实现,并且只需配置一次即可。

    XML:您可以在任何地方注入(inject)任何东西

    您可以在Guice中轻松地做到这一点,我想您也可以在CDI中做到这一点。因此,这并不是绝对禁止您使用基于注释的配置系统来执行此操作。就是说,我敢说大多数应用程序中的大多数注入(inject)类都是可以向自己添加@Inject的类(如果尚不存在)。轻便的标准Java注释库(JSR-330)的存在使将来更多库和框架更容易为组件提供带有@Inject注释的构造函数。

    一个接口(interface)的多个实现

    限定词是解决此问题的一种方法,在大多数情况下应该很好。但是,在某些情况下,您确实想做一些事情,即在特定注入(inject)类中的参数上使用限定符不起作用……通常是因为您希望拥有该类的多个实例,每个实例都使用不同的接口(interface)实现或实例。 Guice用称为PrivateModule的东西解决了这个问题。我不知道CDI在这方面能提供什么。但是同样,这种情况很少见,只要您能够处理它,就不值得让其余的配置受苦。

    关于java - Java依赖注入(inject): XML or annotations,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4995170/

    相关文章:

    Spring @Transactional 值参数与 SpEL(Spring 表达式语言)

    java - 未找到泽西端点

    java - 将 java javax.inject.Provider 与 Spring @Scope(BeanDefinition.SCOPE_PROTOTYPE) 一起使用

    java - 为字母计数器编写构造函数

    java - 当您可以只使用具体类型时,为什么会有带有上限的通配符?

    Java每n行追加换行符

    java.lang.IllegalStateException : Received message from unsupported version: [2. 0 .0] 最低兼容版本是 : [5. 0.0]

    java - Spring 类必须是 AutoWire 属性的组件吗?

    java - @Inject 在 java EE 中给出 NullPointer 异常

    java - 尝试将可序列化对象写入文件时出现 NotSerializedException