XML 配置与基于注释的配置

在我最近从事的一些大型项目中,选择其中一个(XML 或注释)似乎变得越来越重要。随着项目的增长,一致性对可维护性非常重要。

我的问题是: 与基于注释的配置相比,基于 XML 的配置有哪些优点? 与基于 XML 的配置相比,基于注释的配置有哪些优点?

81458 次浏览

我可能错了,但我认为注释(就像 Java 的@Tag 和 C # 的[ Attribute ])是一个编译时选项,而 XML 是一个运行时选项。在我看来,这两者并不等同,而且有着不同的利弊。

这是经典的“配置与约定”问题。在大多数情况下,个人品味决定了答案。然而,就我个人而言,我更喜欢配置(即基于 XML)而不是约定。IMO IDE 的健壮性足以克服人们经常将构建和维护基于 XML 的方法联系在一起的一些 XML 地狱。最后,我发现从长远来看,Configuration 的好处(比如构建用于构建、维护和部署 XML 配置文件的实用程序)要大于惯例。

它取决于您想要配置的所有内容,因为有一些选项不能用注释配置。如果我们从注释的角度来看:

  • 附加: 注释不那么多话
  • 减号: 注释不太可见

重要的是你自己。

一般来说,我会建议选择一种方式,并使用它在一些封闭的产品的一部分..。

(除了一些例外: 例如,如果您选择基于 XML 的配置,可以使用@Autowire 注释。它是混合的,但是这一个有助于可读性和可维护性)

我总是认为注释是类能够做到的 什么的某种指示器,或者 怎么做与其他类交互的指示器。

另一方面,Spring XML 配置对我来说就是 配置

例如,有关代理的 ip 和端口的信息,肯定会进入 XML 文件,这是运行时配置。

使用 @Autowire@Element来指示框架如何处理类是对注释的良好使用。

将 URL 放入 @Webservice注释是不好的风格。

但这只是我的个人观点。 交互和配置之间的界限并不总是清晰的。

注释有它们的用途,但它们不是杀死 XML 配置的灵丹妙药。我建议将两者混合使用!

例如,如果使用 Spring,在应用程序的依赖注入部分使用 XML 是完全直观的。这使代码的依赖性远离将要使用它的代码,相比之下,在需要依赖性的代码中使用某种注释可以使代码意识到这种自动配置。

但是,不使用 XML 进行事务管理,而是使用注释将方法标记为事务性的,这非常有意义,因为这是程序员可能希望了解的信息。但是接口将被注入为 SubtypeY 而不是 SubtypeX 不应该包含在类中,因为如果现在你想注入 SubtypeX,你必须改变你的代码,反正之前你有一个接口协议,所以对于 XML,你只需要改变 XML 映射,这样做是相当快速和轻松的。

我没有使用过 JPA 注释,所以我不知道它们有多好,但是我认为将 bean 映射到 XML 数据库也是好的,因为对象不应该关心它的信息来自哪里,它应该只关心它能用它的信息做什么。但是如果你喜欢 JPA (我没有任何使用它的经验) ,无论如何,去做吧。

一般来说: 如果一个注释提供了功能,并且它本身就是一个注释,并且没有将代码绑定到某个特定的过程中,以便在没有这个注释的情况下正常运行,那么可以使用注释。例如,标记为事务性的事务性方法不会杀死其操作逻辑,而且还可以作为良好的代码级注释。否则,这些信息可能最好用 XML 表示,因为尽管它最终会影响代码的操作方式,但它不会改变代码的主要功能,因此不属于源文件。

我还认为混合是最好的选择,但这也取决于配置参数的类型。 我正在做一个 Seam 项目,它也使用 Spring,我通常将它部署到不同的开发和测试服务器上。所以我分手了:

  • 服务器特定配置(如服务器上资源的绝对路径) : Spring XML 文件
  • 作为其他 bean 的成员注入 bean (或者在许多 bean 中重用 Spring XML 定义的值) : 注释

关键区别在于,您不必为所有更改的服务器特定配置重新编译代码,只需编辑 xml 文件即可。 还有一个好处是,一些配置更改可以由不理解所有代码的团队成员来完成。

我两样都用。主要是 XML,但是当我有一组从公共类继承的 bean 并且具有公共属性时,我会在超类中对这些 bean 使用注释,这样就不必为每个 bean 设置相同的属性。因为我有点控制狂,所以我使用@Resource (name = “ refredBean”)来代替自动装配的东西(如果我需要另一个与最初的 ReferredBean 属于同一个类的 bean,这会为我省去很多麻烦)。

使用纯注释方法的一个重要部分是“ bean 名称”的概念或多或少地消失了(变得无关紧要)。

Spring 中的“ bean 名称”在实现类之上形成了一个额外的抽象级别。使用 XMLbean 定义并引用相对于其 bean 名称的 bean。通过注释,它们被它们的类/接口引用。(虽然 bean 名存在,但您不需要知道它)

我坚信摆脱多余的抽象可以简化系统并提高生产力。对于 很大项目,我认为摆脱 XML 带来的好处是巨大的。

到现在为止,我已经使用 Spring 好几年了,所需的 XML 数量确实越来越令人厌烦。在 Spring 2.5新的 XML 模式和注释支持之间,我通常会做这些事情:

  1. 使用“组件扫描”自动加载使用@Repository、@Service 或@Component 的类。我通常给每个 bean 一个名称,然后使用@Resource 将它们连接在一起。我发现这个管道并不经常改变,所以注释是有意义的。

  2. 对所有 AOP 使用“ AOP”命名空间。这真的很管用。我仍然使用它进行事务处理,因为把@Transactional 放在任何地方都是一种拖累。您可以为任何服务或存储库上的方法创建命名切入点,并快速应用通知。

  3. 我使用 LocalContainerEntityManagerFactoryBean 和 HibernateJpaVendorAdapter 配置 Hibernate。这使 Hibernate 可以轻松地在类路径上自动发现@Entity 类。然后,我使用引用 LCEMFB 的“工厂 bean”和“工厂方法”创建一个名为 SessionFactory 的 bean。

我认为可见性是基于 XML 方法的一大胜利。我发现,考虑到用于导航 XML 文档的各种工具(比如 Visual Studio + ReSharper 的文件结构窗口) ,XML 实际上并没有那么糟糕。

您当然可以采取混合的方法,但是这对我来说似乎很危险,因为这可能会使项目中的新开发人员难以找出不同对象的配置或映射位置。

我不知道; 归根结底,XML 地狱对我来说似乎并没有那么糟糕。

这里有一个更广泛的问题,即外部化元数据和内联元数据的问题。如果您的对象模型只以一种方式持久化,那么内联元数据(即注释)将更加紧凑和可读。

但是,如果对象模型在不同的应用程序中被重用,以至于每个应用程序都希望以不同的方式持久化该模型,那么外部化元数据(即 XML 描述符)就变得更加合适。

两者都不是更好的,因此都受到支持,尽管注释更为流行。因此,像 JPA 这样的新的“毛发着火”框架倾向于更加强调它们。更成熟的 API (如本地 Hibernate)同时提供了这两种功能,因为众所周知,这两种功能都不够。

在 DI 容器的范围内,我认为基于注释的 DI 滥用了 Java 注释的使用。因此,我不建议在您的项目中广泛使用它。如果您的项目确实需要 DI 容器的强大功能,我建议使用 Spring IoC 和基于 XML 的配置选项。

如果只是为了进行单元测试,那么开发人员应该在编码中应用 Dependency Injectpattern,并利用 EasyMock 或 JMock 等模拟工具来规避依赖性。

您应该尽量避免在错误的上下文中使用 DI 容器。

还有其他方面需要比较,比如重构和其他代码更改。在使用 XML 时,需要认真地进行重构,因为您必须处理所有的 XML 内容。但是在使用注释时很容易。

我的首选方法是基于 Java 的配置,不需要(或最少的)注释

根据我的经验,注释配置有一些优点和缺点:

  • 当涉及到 JPA 配置时,因为它只完成一次,而且通常不会经常更改,所以我更喜欢使用注释配置。可能需要考虑看到更大的配置图的可能性——在本例中,我使用的是 MSQLWorkbench 图。
  • XML 配置非常有利于更全面地了解应用程序,但是在运行时之前发现一些错误可能比较麻烦。在这种情况下,Spring @ 配置注释听起来是一个更好的选择,因为它可以让您看到更大的图片,并且还允许在编译时验证配置。
  • 至于 Spring 配置,我倾向于将两种方法结合起来: 对于 dataSource 和 Spring 配置,使用带有 Services 和 Query 接口的 @ 配置注释和 xml 配置,比如 context: Component-scanner base-package = “ ... ...”
  • 但是,当涉及到流配置(Spring Web Flow 或 Lexaden Web Flow)时,xml 配置比 java 注释更重要,因为了解整个业务流程的更大图片是非常重要的。使用注释方法实现它听起来很麻烦。

我更喜欢将这两种方法结合起来—— java 注释和最小化配置地狱的基本 xml。

总是链接到特定 Java 组件(类、方法或字段)的配置信息是用注释表示的一个很好的候选者。在这种情况下,当配置是代码用途的核心时,注释工作得特别好。由于注释的限制,当每个组件只能有一个配置时也是最好的。如果您需要处理多个配置,尤其是那些以包含注释的 Java 类之外的任何内容为条件的配置,那么注释可能会带来比它们解决的问题更多的问题。最后,如果不重新编译 Java 源代码,就不能修改注释,因此在运行时需要重新配置的任何内容都不能使用注释。

请参考下面的链接。他们也可能是有用的。

  1. 注释与 XML 的优缺点
  2. Http://www.ibm.com/developerworks/library/j-cwt08025/

对于 Spring 框架,我喜欢这样的想法,即能够使用@Component 注释并设置“组件扫描”选项,这样 Spring 就可以找到我的 java bean,这样我就不必用 XML 或 JavaConfig 定义所有的 bean。例如,对于只需要连接到其他类(理想情况下通过接口)的无状态单例 java bean,这种方法非常有效。一般来说,对于 Spring bean,我已经在很大程度上放弃了 Spring XML DSL 来定义 bean,现在更倾向于使用 JavaConfig 和 Spring 注释,因为可以对配置进行一些编译时检查,还可以获得一些 Spring XML 配置无法提供的重构支持。在某些罕见的情况下,我发现 JavaConfig/Annotations 不能完成使用 XML 配置可以完成的任务,因此我将两者混合使用。

对于 Hibernate ORM (还没有使用 JPA) ,我仍然喜欢 XML 映射文件,因为领域模型类中的注释在某种程度上违反了我在过去几年中采用的分层架构风格 清洁建筑。之所以会出现这种冲突,是因为它要求核心层依赖于与持久性相关的东西,比如 Hibernate 或 JPA 库,并且它使得域模型 POJO 对持久性的了解少了一些。事实上,核心层根本不应该依赖于任何其他基础设施。

然而,如果 The Clean Architecture 不是你的“茶杯”,那么我可以看到在领域模型类中使用 Hibernate/JPA 注释比单独的 XML 映射文件有明显的优势(比如方便性和可维护性)。