# 编写配置文件的 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 对象。 不要尝试玩得更聪明。 只需遵循基础知识即可。

如果您对以上几点有异议，请给我评论。

学习愉快！