💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# 编写配置文件的 13 个 Spring 最佳实践 > 原文: [https://howtodoinjava.com/best-practices/13-best-practices-for-writing-spring-configuration-files/](https://howtodoinjava.com/best-practices/13-best-practices-for-writing-spring-configuration-files/) Spring 是一个功能强大的框架,它使用多种配置选项。 它的最佳功能是为称为 bean 的纯 Java 对象(PO​​JO)提供企业服务。 Spring 使用[依赖项注入(DI)](https://howtodoinjava.com/spring/spring-core/inversion-of-control-ioc-and-dependency-injection-di-patterns-in-spring-framework-and-related-interview-questions/)来简化并提高[可测试性](https://howtodoinjava.com/best-practices/unit-testing-best-practices-junit-reference-guide/)。 Spring Bean,依赖项和 Bean 所需的服务在 xml 配置文件或注解中指定。 但是,XML 配置文件是冗长且更干净的。 如果未正确计划和编写,在大型项目中将变得非常难以管理。 在本文中,我将向您展示 13 个[最佳实践](https://howtodoinjava.com/java-best-practices/),用于编写 spring XML 配置。 其中一些似乎是最佳实践而不是最佳实践,但我将它们包含在此处是因为它们与该主题高度相关。 > 注意:其他一些因素(例如应用程序设计)可能会影响 XML 配置决策,但是我主要关注 XML 配置的可读性和可维护性。 让我们详细讨论上面的每一个,以使其更有意义。 ## 1)在每个配置文件中添加标题注解 我总是更加强调代码注解。 配置文件也是如此。 添加配置文件标头总是非常有帮助的,该标头总结了配置文件中定义的 bean /属性。 在 Spring 配置中,您可以像添加 XML 注解一样添加注解,也可以使用`description`元素。 例如: `applicationContext.xml` ```java <beans> <description> This configuration file will have all beans which may be used for controlling transactions. </description> ... </beans> ``` 使用`description`标签的一个可能的优点是,某些工具可能会从此元素中获取描述,以在其他地方为您提供帮助。 ## 2)使用一致的命名约定 在所有配置文件中使用相同的命名是非常重要的。 在整个项目中使用清晰,描述性和一致的名称约定,可以提高配置文件的可读性,并使其他开发人员可以轻松避免一些偶然的错误。 例如,对于 bean ID,可以遵循 Java 类字段名称约定。 `EmployeeUpdateDAO`实例的 bean ID 将是`employeeUpdateDAO`。 对于大型项目,可以将包名称添加为 Bean ID 的前缀。 例如 `finance.employeeUpdateDAO`。 ## 3)模式引用中没有版本号 我在之前的文章中也指出了此功能。 我再次将其包括在内,因为从长远来看,它对于改善可维护性至关重要且有益。 要刷新您的内存,根本不需要在 bean 配置文件中为引用的模式指定版本号,您可以忽略它。 如果确实如此,您应该一直忽略它。 Spring 自动从项目依赖项(jar)中选择可用的最高版本。 另外,随着项目的发展和 Spring 版本的更新,我们不必维护所有 XML 配置文件即可看到新功能。 > 阅读更多: [Spring 版本较少的架构引用](https://howtodoinjava.com/spring/spring-core/do-not-specify-version-numbers-in-spring-schema-references/) 一个示例示例将如下所示: `applicationContext.xml` ```java <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Other bean definitions--> </beans> ``` ## 4)优先使用 setter 注入而不是构造方法注入 Spring 提供了三种类型的依赖项注入:`constructor`注入,`setter`注入和`method`注入。 通常,我们都只使用前两种类型。 `applicationContext.xml` ```java <!-- Constructor injection --> <bean id="employeeDAO" class="com.howtodoinjava.dao.EmployeeDAO"> <constructor-arg ref="datasource"/> </bean> <!-- Setter injection --> <bean id="employeeDAO" class="com.howtodoinjava.dao.EmployeeDAO"> <property name="datasource" ref="datasource"> </bean> ``` 构造函数注入可以提供最便宜的线程安全,即[不可变对象](https://howtodoinjava.com/java/related-concepts/how-to-make-a-java-class-immutable/)。 此外,它还可以确保没有完成初始化就不会将对象移交给其他 bean。 塞特特注入剂提供了非常理想的功能,即灵活性或可维护性。 如果在 bean 中要设置多个属性,那么为构造函数创建一长串参数不是一个好主意。 同样,如果可能的话,某些属性可能是可选的。 更喜欢灵活性。 为了保持不变或线程安全,请遵循其他编程规则。 > 阅读更多:[如何使 Java 类不可变](https://howtodoinjava.com/java/related-concepts/how-to-make-a-java-class-immutable/) ## 5)在构造函数注入中将类型优先于索引以进行构造函数参数匹配 最好避免使用`constructor`注入,而更喜欢使用`setter`注入进行依赖项注入。 但是,如果绝对需要使用`constructor`注入,则**总是更喜欢基于类型而不是索引**的参数匹配。 `applicationContext.xml` ```java <!-- Index based constructor injection --> <bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAO"> <constructor-arg index="0" value="rest"/> <constructor-arg index="1" value="8080"/> </bean> <!-- Type based constructor injection --> <bean id="employeeDAO" class="com.howtodoinjava.EmployeeDAO"> <constructor-arg type="java.lang.String" value="rest"/> <constructor-arg type="int" value="8080"/> </bean> ``` 如您所见,基于类型的参数传递更具可读性,并且不易出错。 但是,只要基于类型的参数传递有任何歧义,就可以毫不犹豫地转到基于索引的参数传递。 ## 6)在扩展形式上使用快捷方式形式 Spring bean 配置语义允许两种形式来指定属性值和其他 bean 引用。 一种是扩展形式,另一种是较短形式。 最好使用较短的版本。 `applicationContext.xml` ```java <!-- Expanded version --> <bean id="employeeDAO" class="com.howtodoinjava.dao.EmployeeDAO"> <property name="datasource"> <ref bean="datasource"></ref> <value>datasource</value> </property> </bean> <!-- Shorter/shortcut version --> <bean id="employeeDAO" class="com.howtodoinjava.dao.EmployeeDAO"> <property name="datasource" ref="datasource" value="datasource"> </bean> ``` ## 7)尽可能重用 bean 定义 Spring 提供了非常有用的功能,您应该在项目中广泛使用它,即 bean 定义可重用性。 在这里,我不是在谈论用于 setter 注入的 bean 参考。 而是我指出了在构造其他 bean 时重用 bean 定义。 以数据源定义的示例为例: `applicationContext.xml` ```java <bean id="abstractDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> <bean id="concreteDataSourceOne" parent="abstractDataSource" p:url="${jdbc.databaseurlOne}"/> <bean id="concreteDataSourceTwo" parent="abstractDataSource" p:url="${jdbc.databaseurlTwo}"/> ``` > 阅读更多: [Spring AbstractRoutingDataSource 示例](https://howtodoinjava.com/spring/spring-orm/spring-3-2-5-abstractroutingdatasource-example/) ## 8)始终使用`id`作为 bean 标识符 Spring 允许 bean 使用两种类型的标识符。 使用属性`id`或`name`。 您应该**始终选择属性 ID 而不是名称**。 通常,它既不会增加可读性,也不会增加任何性能。 这是行业标准的做法,所有其他开发人员都在全世界甚至在您的团队中遵循。 只是不要在这里是个奇怪的人。 ## 9)尽量避免自动装配 如果可以长期管理,自动装配是一个很棒的功能。 通常,如果您的项目只有很少的 bean,并且几乎可以在内存中记住它们,那将是有益的。 一旦项目变大,自动装配就开始在确定要使用的正确依赖项切面造成麻烦。 我发现主要的缺点是无法将整个系统绑定在一起。 这是 spring 配置文件获胜的地方。 他们可以在几分钟之内将整个系统呈现给任何新手。 另外,当您开始调试一些复杂的问题时,所有在配置文件中的所有信息实际上都会有很大帮助。 自动装配使调试更加困难。 > 了解更多:[Spring 自动装配](https://howtodoinjava.com/2013/05/08/spring-beans-autowiring-concepts/) ## 10)始终使用`classpath`前缀 导入资源,XML 配置,属性等时,请始终使用`classpath:`或`classpath*:`前缀。 这提供了资源位置的一致性和清晰度。 并非 Spring 的每个功能都具有相同的行为,**`classpath:`保证一致性**。 类路径由构建工具和 IDE 确定。 对于 Java 代码,通常为`src/main/java`,对于非 Java 依赖项和测试通常为`src/main/resources`,对于 Java 代码为`src/test/java`,对于非 Java 资源为`src/test/resources`。 `applicationContext.xml` ```java <!-- Always use classpath: prefix--> <import resource="classpath:/META-INF/spring/applicationContext-security.xml"/> ``` ## 11)总是外部化属性 通常,存在与应用程序运行时间相关的多个配置参数。 它们被传递到 bean 配置上下文文件中的 bean 定义。 不要将它们硬编码在配置文件中。 而是将它们外部化到某些属性文件。 最好根据它们的用途或模块将它们分组在单独的文件中,即`jdbc.properties`文件中所有与 JDBC 数据源相关的属性。 `applicationContext.xml` ```java <bean id="abstractDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:username="${jdbc.username}" p:password="${jdbc.password}" /> ``` 和属性文件是: `jdbc.properties` ```java jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.username=root jdbc.password=password ``` ## 12)在开发阶段使用“依赖检查” 您应该将 Bean 定义上的`dependency-check`属性设置为`simple`,`objects`或`all`(默认值为`none`,即不检查),以便容器可以为您执行显式依赖项验证。 当必须显式地或通过自动装配来设置 Bean 的所有属性(或某些类别的属性)时,这很有用。 `applicationContext.xml` ```java <bean id="abstractDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="${jdbc.driverClassName}" p:username="${jdbc.username}" p:password="${jdbc.password}" dependency-check="all" /> ``` 在上面给出的示例中,容器将确保在应用程序初始化时间本身中设置数据源的所有属性/参数。 ## 13)不要滥用/滥用依赖注入 最后,请不要滥用引入[依赖注入](https://howtodoinjava.com/spring/spring-core/inversion-of-control-ioc-and-dependency-injection-di-patterns-in-spring-framework-and-related-interview-questions/)的动机。 Java 提供`new`关键字来创建新对象。 在不需要 DI 的地方使用此精彩的关键字,例如 DTO 对象。 不要尝试玩得更聪明。 只需遵循基础知识即可。 如果您对以上几点有异议,请给我评论。 学习愉快!