如上所述,我们定义了一个PropertyPlaceholderConfigurer类的实例,并将其位置属性设置为我们的属性文件。TW.WInGWIt.COM该类被实现为Bean工厂的后处理器,并将使用定义在文件中的属性来代替所有的占位符(${...}value)。
利用这种技术,我们可以从applicationContext.XML中移除所有特定于主机的配置属性。通过这种方式,我们可以自由地为该文件添加新的Bean,而不必担心特定于主机属性的同步性。这样可以简化生产部署和维护。
同步性连接
上面的技术解决了第一个问题,可是如果您计划修改不同应用程序部署之间的Bean连接,这一技术便不很适合。针对这一问题的一个解决方案便是额外创建一个名为applicationContext-[hostname].xml 的XML定义文件。其中[hostname]是部署应用程序的主机的名称。例如,在本地的机器上,这个文件通常名为 applicationContext-localhost.xml,而在部署时,它可能更名为applicationContext- .xml。
可以猜测,这一文件必须包括特定于某一主机的所有配置Bean。在本文中,我们将假设dataSource bean定义将位于这类文件中,而不是通用的applicationContext.xml定义。当然,这种机制与前者并非沖突,但是为了更加简单明了,我们将只关注这种方法。
既然我们已经有了特定的配置,下面我们就来讨论一下如何将其整合到整个Spring MVC框架配置概念中。要达到这一目的,可以有许多方法,我们将详细地一一说明。但首先,我们应该注意到,由于有些Bean可能位于独立的配置文件中,因此在 applicationContext.xml中,所有对它们的局部引用都必须更换成全局名称。
例如,如下引用:
<propertyname="someProperty">
<reflocal="someBean"/>
</property>
应更改为:
<propertyname="someProperty">
<refbean="someBean"/>
</property>
在这之后,我们有很多可以添加额外的资源以用于配置的方式。其中最明显的就是使用标签将这一额外资源包含在 applicationContext.xml配置文件中。使用时,要将该标签放在applicationContext.xml文件开头。例如:
<importresource="application.xml"/>
现在,在独立的XML定义文件和普通的应用程序上下文定义文件中的所有通用Bean定义都有了特定于主机的连接。由于大多数的Bean都不是特定于主机的,因此我们可以像处理Web应用程序中的其他资源一样自由地处理applicationContext.xml文件,并可以通过合适的版本控制系统与其进行同步。
但是,上述方法也有一定的弊端。如果您想保留不同XML文件的不同配置,就仍然必须担心applicationContext.xml的同步性,因为资源的名称必须根据不同服务器进行更改。虽然与原有的解决方案相比有了很大提高,只需更改文件名,但是这还是需要开发人员的手动协助。
由于与applicationContext.xml相比,主机配置不需如此频繁地进行更改,因此下一步便是将主机配置移动到web.xml文件中(如果可能的话)。幸运的是,我们有一个可用的解决方案。看一下下面关于web.xml配置的片断:
<listener>
<listener-class>org.sprntext.ContextLoaderListener
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation
</param-name>
<param-value>/WEB-INF/applicationContext.xml/WEB-INF/application.xml
</param-value>
</context-param>
正如您所看到的,除了web.xml文件中常有的ContextLoaderListener之外,我们还添加了 contextConfigLocation上下文参数配置。这一参数用于指示框架查找这些配置文件的位置。如果这一参数被省略,则Spring就只能到 applicationContext.xml中查找。这里我们也定义了特定于主机的配置文件来使用。
利用这种方法,我们将所有特定于主机的配置从applicationContext.xml文件中移除,这样便减轻了其在不同应用程序部署中的同步性。
如果这种方法成为您的新习惯,您还可以使其更加灵活。通过遵守下列指令,也可以将特定于主机的配置从web.xml文件中移除。
为此,需要创建特定于我们的应用程序上下文的类:
packagenet.nighttale.spring.util;
import.InetAddress;
importorg.sprntext.support.XmlWebApplicationContext;
publicclassPerHostXmlWebApplicationContext
extendsXmlWebApplicationContext...{
protectedString[]getDefaultConfigLocations()...{
Stringhostname="localhost";
try...{
hostname=InetAddress.getLocalHost().getHostName();
}catch(Exceptione)...{
}
StringperHostConfiguration=DEFAULT_CONFIG_LOCATION_PREFIX
+"applicationContext-"
+hostname
+DEFAULT_CONFIG_LOCATION_SUFFIX
;
logger.debug(
"Addingperhostconfigurationfile:"
+perHostConfiguration
);
if(getNamespace()!=null)...{
returnnewString[]...{
DEFAULT_CONFIG_LOCATION_PREFIX
+getNamespace()
+DEFAULT_CONFIG_LOCATION_SUFFIX
,perHostConfiguration};
}
else...{
returnnewString[]...{
DEFAULT_CONFIG_LOCATION
,perHostConfiguration};
}
}
}
这个类拓展了Spring中常被作为默认值使用的XmlWebApplicationContext。 XmlWebApplicationContext类将Web应用程序的配置从XML定义文件中复制过来。默认情况下,它可以配置来自 applicationContext.xml和[Servlet-name]-servlet.xml文件中的应用程序。这个类执行的惟一一项额外任务便是获取它所在的主机名称,并将applicationContext-[hostname].xml文件添加到配置文件列表中。
为了使用这个类,我们需要对其进行编译,将其包含在类途径中,并指示Spring框架使用它。前两步非常简单,我们就不在此赘述。我们可以指示Sping通过contextClass上下文参数来使用它。除了web.xml文件中的原有配置,我们还可以添加下列内容:
<context-param>
<param-name>contextClass</param-name>
<param-value>net.nighttale.spring.util.PerHostXmlWebApplicationContext
</param-value>
</context-param>
如果我们使用这一配置片断,将会有三个文件被用于初始化这个框架:[servlet-name]-servlet.xml、applicationContext-[hostname].xml以及applicationContext.xml。
正如您所看到的,applicationContext.xml和web.xml文件已经完全摆脱了任何特定的配置细节,而且您也不必担心会在更新应用程序时破坏配置。
但是,这种方法有一个不足之处。因为,不论是否会使用,都需要在应用程序部署中有第三个配置文件。在这种情况下,便不需要特定于主机的配置。例如:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN"
"-beans.dtd">
<beans>
</beans>