日期:2014-05-19  浏览次数:20639 次

若干条J2EE应用中运用“配置”的最佳实践
本文所提到的所有内容的前提是使用一些开源框架搭建简单的J2EE应用时,对配置的运用方面的一些总结出来的最佳实践。

1. 尽最大的可能简化你的配置

这一点似乎是基本原则,没有人会愿意多写一行代码,配置也是代码,多一行配置,就意味着多一行的维护量。简化配置的主要途径大致有:
1) 尽可能减少配置文件的数量
2) 使用语义鲜明的Annotation来代替复杂的XML文件配置
3) 使用CoC来代替配置文件
4) 使用一些特殊的技巧来简化配置文件的内容

2. 分离关注点,让配置文件各尽其用

这一点似乎与第一点有所背离,不过事实上,分离关注点对于配置文件的可维护性是非常重要的一点。

举一个针对Spring+Hibernate的配置场景作为例子。通常我们需要一个Spring的配置文件(applicationContext.xml),来配置DataSource和SessionFactory,由于Spring本身提供了针对Hibernate的Global属性进行配置的选项,所以,其实我们可以通过如下的配置文件,对Spring+Hibernate完成配置:


<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="mappingResources">
        <list>
           <value>com/demo2do/demo/entity/User.hbm.xml</value>
           <value>com/demo2do/demo/entity/Order.hbm.xml</value>
           <value>com/demo2do/demo/entity/Admin.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
           <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
           <prop key="hibernate.show_sql">true</prop>
        </props>
     </property>
</bean>


在这里,我们发现,一个SessionFactory的配置实在太长了,一旦我们需要对其中的某些配置进行改动,就需要用肉眼去观察我们所需要修改的配置片段。在项目开发过程中,我们会发现,这个文件的这个配置片段修改频度会非常高,因为在一个团队中,每个人都可能需要增加一个持久化类,或者对hibernate进行一些全局化的配置修改。结果,这段配置可能会在版本管理上造成merge的混乱。

所以,我们可以在这个基础上对这段配置进行重构,重构的原则就在于把Hibernate的配置和Spring的配置进行关注点分离。我们选择hibernate.properties对Hibernate的一些Global的选项进行指定。同时使用指定持久化类hbm配置文件路径的方式,批量定义持久化类。重构后的配置文件变成了2个:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="mappingDirectoryLocations">
            <list>
				<value>classpath*:persist/system</value>
				<value>classpath*:persist/role</value>
				<value>classpath*:persist/activity</value>
				<value>classpath*:persist/extension</value>
				<value>classpath*:persist/user</value>
            </list>
        </property>
</bean>


######################
### Query Language ###
######################

## define query language constants / function names
hibernate.query.substitutions true 1, false 0, yes 'Y', no 'N'

#################
### Platforms ###
#################

## MySQL

hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
hibernate.connection.url jdbc:mysql://127.0.0.1:3306/test
hibernate.connection.username root
hibernate.connection.password root

## Oracle

#hibernate.dialect org.hibernate.dialect.OracleDialect

....


此时,我们可以发现,程序员可以独立工作,不需要为增加持久化类修改公共配置而烦恼,hibernate.properties也更加清晰的反映hibernate相关的配置。

这还不够,因为在项目中,我们往往可能在不同的DataSource的实现上切换。多数情况下,我们会使用类似C3P0这样的数据连接池,当然,也可能会通过JNDI来指定我们的DataSource。所以,我们在这里很有必要对JDBC连接相关的关注点再一次进行分离。引入一个jdbc.properties的文件指定JDBC相关的链接信息,并在Spring配置文件中导入这些配置:

<!-- A Local dataSource Definition using c3p0 connection pool -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"	destroy-method="close">
		<property name="driverClass" value="${connection.driver_class}"/>
		<property name="jdbcUrl" value="${jdbc.connection.url}"/>
		<property name="idleConnectionTestPeriod" value="${jdbc.pool.c3p0.idle_connection_test_period}" />
		<property name="preferredTestQuery" value="${jdbc.pool.c3p0.preferred_test_query}" />
		<property name="maxIdleTime" value="${jdbc.pool.c3p0.max_idle_time}" />
		<property name="properties">
			<props>
				<prop key="user">${jdbc.connection.username}</prop>
				<prop key="password">${jdbc.connection.password}</prop>
				<