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

Spring is a powerful Java application framework, used in a wide range of configuration options. Its best feature if that it provides enterprise services to Plain Old Java Objects (POJOs) called beans. Spring uses dependency injection (DI) to achieve simplification and increased testability. Spring beans, dependencies, and the services needed by beans are specified in xml configuration files or annotations. The XML configuration files, however, are verbose and more clean. If not planned and written correctly, it becomes very hard to manage in big projects.

In this article, I will show you 10 best practices for writing spring XML configurations. Some of them may seem more necessary practices rather than best practices, yet I have included them in here because they were highly related to the topic.

Note: Some other factors, such as application design, can impact the XML configuration decisions but I am focusing on the XML configuration’s readability and manageability only.



1) Add a header comment to each configuration file
2) Use consistent naming conventions
3) No version numbers in schema references
4) Prefer setter injection over constructor injection
5) Prefer type over index for constructor argument matching
6) Use shortcut forms over expanded forms
7) Reuse bean definitions as much as possible
8) Always use ids as bean identifiers
9) Try to avoid autowiring
10) Always use classpath prefix
11) Always externalize properties
12) Use dependency-check at the development phase
13) Do not abuse/overuse dependency injection
Lets discuss each of above in detail to make more sense.



1) Add a header comment to each configuration file

I always put more stress on code comments. The same goes for configuration files also. It is always very helpful to add a configuration file header, which summarizes the beans/properties defined in the configuration files.

In spring configuration, you can add comments as adding xml comments or you can use the description element. For example:

1
2
3
4
5
6
7
<beans>
    <description>
        This configuration file will have all beans
        which may be used for controlling transactions.
    </description>
    ...
</beans>

One possible advantage of using the description tag is that some tools may pick up the description from this element to help you in other places.

2) Use consistent naming conventions

This is very important thing that you use same naming across all configuration files. Using clear, descriptive, and consistent name conventions across the project increase the readability of configuration files and make it easy for other developers to avoid some accidental bugs.

For bean ID, for example, you can follow the Java class field name convention. The bean ID for an instance of EmployeeUpdateDAO would be employeeUpdateDAO. For large projects, you can add the package name as the prefix of the bean ID. e.g. finance.employeeUpdateDAO.

3) No version numbers in schema references

I have also pointed out this feature earlier in previous post. I am again including it because it is essential and beneficial in long term specially to reduce maintainbility. To refresh your memory, specifying version number in bean configuration files for referenced schemas are not mandatory at all, and you can omit it. If fact, you should omit it all the time.

Spring automatically picks the highest version available from the project dependencies (jars). Also, as the project evolves and the Spring version will be updated, we won’t have to maintain all the XML config files to see the new features.

Read More: Do not specify version numbers in Spring schema references

A sample example will be like this:

1
2
3
4
5
6
7
8
9
10
11
12

4) Prefer setter injection over constructor injection

Spring provides three types of dependency injection: constructor injection, setter injection, and method injection. Usually, we all use first two types only.

1
2
3
4
5
6
7
8
9
<!-- Constructor injection -->
<beanid="employeeDAO"  class="com.howtodoinjava.dao.EmployeeDAO">
    <constructor-argref="datasource"/>
</bean>
 
<!-- Setter injection -->
<beanid="employeeDAO"class="com.howtodoinjava.dao.EmployeeDAO">
    <propertyname="datasource" ref="datasource">
</bean>

Constructor injection can provide the cheapest thread safety possible i.e. immutable object. Also it guarantees that object will not be handed over to other beans without complete initialization.

Setter injection provides much desired capability i.e. flexibility or maintainability. If there are multiple attributes to set in a bean, then creating a long list of parameters to constructor is not good idea. Also, if is possible that some of the attributes might be optional.

Prefer flexibility. For immutability or thread safety, follow other programming rules.

Read More: How to make a java class immutable

5) Prefer type over index for constructor argument matching in Constructor injection

Better to avoid constructor injection and prefer to use setter injection for dependency injection. But, if you have an absolute requirement to use constructor injection then always prefer parameter matching based on type rather than index.

1
2
3
4
5
6
7
8
9
10
11
<!-- Index based constructor injection -->
<beanid="employeeDAO"class="com.howtodoinjava.EmployeeDAO">
    <constructor-argindex="0"value="rest"/>
    <constructor-argindex="1"value="8080"/>
</bean>
 
<!-- Type based constructor injection -->
<beanid="employeeDAO"class="com.howtodoinjava.EmployeeDAO">
    <constructor-argtype="java.lang.String"value="rest"/>
    <constructor-argtype="int"value="8080"/>
</bean>

As you can see that type based argument passing is more readable and less error prone. But, anytime there is any ambiguity in type based argument passing, go to index based argument passing without hesitation.


6) Use shortcut forms over expanded forms

Spring bean configuration semantics allow two forms for specifying property values and other bean references. One is expanded and other is shorter form. Prefer shorter version.

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Expanded version -->
<beanid="employeeDAO"class="com.howtodoinjava.dao.EmployeeDAO">
    <propertyname="datasource">
        <refbean="datasource"></ref>
        <value>datasource</value>
     </property>
</bean>
 
<!-- Shorter/shortcut version -->
<beanid="employeeDAO"class="com.howtodoinjava.dao.EmployeeDAO">
    <propertyname="datasource" ref="datasource"value="datasource">
</bean>

7) Reuse bean definitions as much as possible

Spring provides a very useful capability which you should use extensively in your project and i.e. bean definition re-usability. Here I am not talking about bean references for setter injection. Rather I am pointing out the bean definition re-use in constructing other beans.

Take an example of datasource definition:

1
2
3
4
5
6
7
8
9
10
11
12
13
<beanid="abstractDataSource"class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
    p:driverClassName="${jdbc.driverClassName}"
    p:username="${jdbc.username}"
    p:password="${jdbc.password}"/>
 
<beanid="concreteDataSourceOne"
    parent="abstractDataSource"
    p:url="${jdbc.databaseurlOne}"/>
  
<beanid="concreteDataSourceTwo"
    parent="abstractDataSource"
    p:url="${jdbc.databaseurlTwo}"/>

Read complete configuration example here: Spring 3.2.5 AbstractRoutingDataSource example

8) Always use ids as bean identifiers

Spring allows two types of identifiers for a bean. Using attribute “id” or by “name”. You should always choose attribute id over name. Usually it does neither increase readability nor benefit any performance scenario. It is just industry standard practice which all fellow developers are following worldwide and even in your team.

Just don’t be odd man out here.

9) Try to avoid autowiring

Autowiring is a great feature if you can manage it in long term. Usually it is beneficial if you project is having very few beans and you can almost remember them all in your memory as well.

As soon as project gets bigger, autowiring starts creating trouble in identifying correct dependency to use. The main drawback, I find is not to have a overview of whole system binded together. This is where spring configuration files win. They can represent the whole system to any new guy in couple of minutes.

Also, when you start debugging some complex issues then all information present in one place in configuration files, actually helps a lot. Autowiring makes debugging harder.

Read More: Spring autowiring concepts

10) Always use classpath prefix

When importing resources, XML config, properties, etc. Always use the classpath: or classpath*: prefix. This provides consistency and clarity to the location of the resource. Not every feature of Spring behaves the same, classpath: guarantees consistency.

The classpath is determined by the build tool and IDE. Usually this is src/main/java for java code, src/main/resources for non-java dependencies and for tests, src/test/java for java code and src/test/resources for non-java resources.

1
2
<!-- Always use classpath: prefix-->
<importresource="classpath:/META-INF/spring/applicationContext-security.xml"/>

11) Always externalize properties

Often there are multiple configuration parameters related to runtime of application. They are passed to bean definitions in bean configuration context file. DO not hard code them in config file. Instead externalize them to some properties file(s).

Better group them in separate files based on their usage or module i.e. all JDBC datasource related properties in jdbc.propertiesfile.

1
2
3
4
5
<beanid="abstractDataSource"class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="${jdbc.driverClassName}"
        p:username="${jdbc.username}"
        p:password="${jdbc.password}"/>

and properties file

1
2
3
4
5
/*  file://jdbc.properties */
 
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=password

12) Use dependency-check at the development phase

You should mostly set the dependency-check attribute on a bean definition to simple, objects, or all (default value is none i.e. no checking), so that the container can do explicit dependency validation for you. It is useful when all of the properties (or certain categories of properties) of a bean must be set explicitly, or via autowiring.

1
2
3
4
5
6
<beanid="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"/>

In above given example, the container will ensure that all properties/parameters to datasource are set in application initialization time itself.

13) Do not abuse/overuse dependency injection

Finally, please do not abuse the motive behind introducing dependency injection. Java provide “new” keyword to create new objects. Use this wonderful keyword where DI is not necessary e.g. DTO objects. Don’t try to play smarter. Just follow the basics.

Drop me a comment if you feel otherwise on any of above points.

Happy Learning !!




转载于:https://my.oschina.net/leyou/blog/468129

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值