134

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

我的问题是:基于 XML 的配置相对于基于注解的配置有哪些优势,基于注解的配置相对于基于 XML 的配置有哪些优势?

4

16 回答 16

203

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

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

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

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

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

于 2008-10-08T15:31:53.513 回答
31

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

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

两者都不是更好,因此两者都受支持,尽管注释更时尚。因此,像 JPA 这样的新框架往往会更加强调它们。更成熟的 API,如原生 Hibernate,两者都提供,因为众所周知,这两者都不够。

于 2009-06-12T13:59:56.970 回答
13

总是将注释视为某种指示类的能力,或者它如何与其他类交互的指标。

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

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

使用@Autowire,@Element来指示框架如何处理类是很好地使用注释。

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

但这只是我的看法。交互和配置之间的界限并不总是很清楚。

于 2008-10-08T13:14:46.723 回答
6

我已经使用 Spring 几年了,所需的 XML 数量肯定变得乏味。在 Spring 2.5 中新的 XML 模式和注释支持之间,我通常会做这些事情:

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

  2. 对所有 AOP 使用“aop”命名空间。这真的很棒。我仍然将它用于交易,因为将@Transactional 放在所有地方有点拖累。您可以为任何服务或存储库上的方法创建命名切入点,并非常快速地应用建议。

  3. 我使用 LocalContainerEntityManagerFactoryBean 和 HibernateJpaVendorAdapter 来配置 Hibernate。这让 Hibernate 可以轻松地自动发现类路径上的 @Entity 类。然后我使用引用 LCEMFB 的“factory-bean”和“factory-method”创建一个命名的 SessionFactory bean。

于 2008-12-02T05:09:42.533 回答
5

使用仅注释方法的一个重要部分是“bean 名称”的概念或多或少地消失了(变得微不足道)。

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

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

于 2008-11-17T13:13:19.270 回答
4

这取决于您要配置的所有内容,因为有些选项无法使用注释进行配置。如果我们从注解的角度来看:

  • 加:注释不那么啰嗦
  • 减号:注释不太明显

由你决定什么更重要......

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

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

于 2008-10-08T12:34:27.693 回答
4

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

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

我不知道; 最后,XML Hell 对我来说似乎并没有那么糟糕。

于 2009-06-12T13:48:08.043 回答
4

还有其他方面可以比较,例如重构和其他代码更改。使用 XML 时,重构需要付出很大的努力,因为您必须处理所有 XML 内容。但是使用注释时很容易。

我首选的方式是基于 Java 的配置,没有(或最少)注释。http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java

于 2012-07-10T07:50:55.617 回答
3

我可能错了,但我认为注释(如 Java 的 @Tag 和 C# 的 [Attribute] 中)是编译时选项,而 XML 是运行时选项。这对我来说是不等同的,并且有不同的优点和缺点。

于 2008-10-08T12:09:08.337 回答
3

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

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

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

于 2008-10-08T16:12:02.280 回答
2

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

如果只是为了单元测试,开发人员应该在他们的编码中应用依赖注入模式,并利用 EasyMock 或 JMock 等模拟工具来规避依赖关系。

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

于 2010-04-03T05:58:05.410 回答
2

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

请参考以下链接。它们也可能有用。

  1. 注释 vs XML,优点和缺点
  2. http://www.ibm.com/developerworks/library/j-cwt08025/
于 2014-03-05T08:43:40.630 回答
1

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

于 2008-10-08T12:20:40.873 回答
1

我两个都用。主要是 XML,但是当我有一堆从公共类继承并具有公共属性的 bean 时,我在超类中为它们使用注释,因此我不必为每个 bean 设置相同的属性。因为我有点控制狂,我使用 @Resource(name="referredBean") 而不仅仅是自动装配的东西(如果我需要另一个与原始引用Bean 相同类的 bean,可以为自己省去很多麻烦) .

于 2008-11-05T16:38:21.020 回答
1

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

  • 当涉及到 JPA 配置时,因为它只完成一次并且通常不会经常更改,所以我更喜欢坚持注释配置。可能会担心看到更大的配置图——在这种情况下,我使用 MSQLWorkbench 图表。
  • XML 配置非常适合获得更大的应用程序图,但在运行之前发现一些错误可能很麻烦。在这种情况下,Spring @Configuration注解听起来是一个更好的选择,因为它也可以让您看到更大的图景,并且还允许在编译时验证配置。
  • 至于 Spring 配置,我更喜欢将这两种方法结合起来:将@Configuration注释与 Services 和 Query 接口和 xml 配置用于 dataSource 和 spring 配置内容,例如 context:component-scan base-package="..."
  • 但是当涉及到流配置(Spring Web Flow 或 Lexaden Web Flow)时,xml 配置位 java 注释,因为看到整个业务流程的更大图景非常重要。使用注释方法实现它听起来很麻烦。

我更喜欢将这两种方法结合起来——Java 注释和基本的 xml 最小值,可以最大限度地减少配置地狱。

于 2013-01-20T09:20:12.113 回答
1

对于 Spring 框架,我喜欢能够使用 @Component 注释并设置“组件扫描”选项的想法,以便 Spring 可以找到我的 java bean,这样我就不必在 XML 中定义我的所有 bean,也不必在Java配置。例如,对于只需要连接到其他类(理想情况下通过接口)的无状态单例 Java bean,这种方法非常有效。一般来说,对于 Spring bean,我大部分时间都从用于定义 bean 的 Spring XML DSL 中移出,现在更倾向于使用 JavaConfig 和 Spring Annotations,因为您可以获得一些编译时检查您的配置和一些您没有的重构支持'无法使用 Spring XML 配置。在我发现 JavaConfig/Annotations 无法完成使用 XML 配置可用的功能的某些极少数情况下,我确实将两者混合使用。

对于 Hibernate ORM(还没有使用过 JPA),我仍然更喜欢 XML 映射文件,因为域模型类中的注释在某种程度上违反了我过去几年采用的分层架构风格的 Clean Architecture 。发生违规是因为它要求核心层依赖于持久性相关的东西,例如 Hibernate 或 JPA 库,并且它使域模型 POJO 对持久性的无知程度降低了一些。事实上,核心层根本不应该依赖任何其他基础设施。

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

于 2014-03-27T16:01:35.833 回答