编写配置文件的 13 个 Spring 最佳实践

编写配置文件的 13 个 Spring 最佳实践

原文: https://howtodoinjava.com/best-practices/13-best-practices-for-writing-spring-configuration-files/

Spring 是一个功能强大的框架,它使用多种配置选项。 它的最佳功能是为称为 bean 的纯 Java 对象(PO​​JO)提供企业服务。 Spring 使用依赖项注入(DI)来简化并提高可测试性

Spring Bean,依赖项和 Bean 所需的服务在 xml 配置文件或注解中指定。 但是,XML 配置文件是冗长且更干净的。 如果未正确计划和编写,在大型项目中将变得非常难以管理。

在本文中,我将向您展示 13 个最佳实践,用于编写 spring XML 配置。 其中一些似乎是最佳实践而不是最佳实践,但我将它们包含在此处是因为它们与该主题高度相关。

注意:其他一些因素(例如应用程序设计)可能会影响 XML 配置决策,但是我主要关注 XML 配置的可读性和可维护性。

让我们详细讨论上面的每一个,以使其更有意义。

1)在每个配置文件中添加标题注解

我总是更加强调代码注解。 配置文件也是如此。 添加配置文件标头总是非常有帮助的,该标头总结了配置文件中定义的 bean /属性。

在 Spring 配置中,您可以像添加 XML 注解一样添加注解,也可以使用description元素。 例如:

applicationContext.xml

<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 版本较少的架构引用

一个示例示例将如下所示:

applicationContext.xml

<?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

<!-- 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>

构造函数注入可以提供最便宜的线程安全,即不可变对象。 此外,它还可以确保没有完成初始化就不会将对象移交给其他 bean。

塞特特注入剂提供了非常理想的功能,即灵活性或可维护性。 如果在 bean 中要设置多个属性,那么为构造函数创建一长串参数不是一个好主意。 同样,如果可能的话,某些属性可能是可选的。

更喜欢灵活性。 为了保持不变或线程安全,请遵循其他编程规则。

阅读更多:如何使 Java 类不可变

5)在构造函数注入中将类型优先于索引以进行构造函数参数匹配

最好避免使用constructor注入,而更喜欢使用setter注入进行依赖项注入。 但是,如果绝对需要使用constructor注入,则总是更喜欢基于类型而不是索引的参数匹配。

applicationContext.xml

<!-- 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

<!-- 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

<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 示例

8)始终使用id作为 bean 标识符

Spring 允许 bean 使用两种类型的标识符。 使用属性idname。 您应该始终选择属性 ID 而不是名称。 通常,它既不会增加可读性,也不会增加任何性能。 这是行业标准的做法,所有其他开发人员都在全世界甚至在您的团队中遵循。

只是不要在这里是个奇怪的人。

9)尽量避免自动装配

如果可以长期管理,自动装配是一个很棒的功能。 通常,如果您的项目只有很少的 bean,并且几乎可以在内存中记住它们,那将是有益的。

一旦项目变大,自动装配就开始在确定要使用的正确依赖项切面造成麻烦。 我发现主要的缺点是无法将整个系统绑定在一起。 这是 spring 配置文件获胜的地方。 他们可以在几分钟之内将整个系统呈现给任何新手。

另外,当您开始调试一些复杂的问题时,所有在配置文件中的所有信息实际上都会有很大帮助。 自动装配使调试更加困难。

了解更多:Spring 自动装配

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

<!-- Always use classpath: prefix-->
<import resource="classpath:/META-INF/spring/applicationContext-security.xml"/>

11)总是外部化属性

通常,存在与应用程序运行时间相关的多个配置参数。 它们被传递到 bean 配置上下文文件中的 bean 定义。 不要将它们硬编码在配置文件中。 而是将它们外部化到某些属性文件。

最好根据它们的用途或模块将它们分组在单独的文件中,即jdbc.properties文件中所有与 JDBC 数据源相关的属性。

applicationContext.xml

<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

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=password

12)在开发阶段使用“依赖检查”

您应该将 Bean 定义上的dependency-check属性设置为simpleobjectsall(默认值为none,即不检查),以便容器可以为您执行显式依赖项验证。 当必须显式地或通过自动装配来设置 Bean 的所有属性(或某些类别的属性)时,这很有用。

applicationContext.xml

<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)不要滥用/滥用依赖注入

最后,请不要滥用引入依赖注入的动机。

Java 提供new关键字来创建新对象。 在不需要 DI 的地方使用此精彩的关键字,例如 DTO 对象。 不要尝试玩得更聪明。 只需遵循基础知识即可。

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

学习愉快!