spring配置xml文件
您的应用程序在运行之前必须工作的环境数量通常取决于几件事,包括您组织的业务流程,应用程序的规模以及它的“重要性”(即,如果您正在编写税收表)系统为您的国家/地区提供税收服务,则测试过程可能比为本地商店编写电子商务应用程序时更为严格。 为使您有所了解,以下是想到的所有不同环境的快速列表(可能不完整):
- 本地开发人员机器
- 开发测试机
- 测试团队功能测试机
- 集成测试机
- 克隆环境(实时副本)
- 生活
这不是一个新问题,通常可以通过为每个环境创建一组Spring XML和属性文件来解决。 XML文件通常包含一个导入其他环境特定文件的主文件。 然后在编译时将它们耦合在一起以创建不同的WAR或EAR文件。 这种方法已经使用了多年,但确实存在一些问题:
- 这是非标准的。 每个组织通常都有自己的解决方案,没有两种方法可以完全相同/
- 很难实现,为错误留出了很大的空间。
- 必须为每个环境创建一个不同的WAR / EAR文件并将其部署在每个环境上,这需要花费时间和精力,这可能会花费更多的时间来编写代码。
Spring bean配置中的差异通常可以分为两部分。 首先,存在特定于环境的属性,例如URL和数据库名称。 通常使用PropertyPlaceholderConfigurer类和相关的$ {}标记将它们注入到Spring XML文件中。
<bean id='propertyConfigurer' class='org.springframework.beans.factory.config.PropertyPlaceholderConfigurer'>
<property name='locations'>
<list>
<value>db.properties</value>
</list>
</property>
</bean>
其次,有特定于环境的bean类,例如数据源,它们通常根据您连接数据库的方式而有所不同。
例如,在开发中,您可能具有:
<bean id='dataSource' class='org.springframework.jdbc.datasource.DriverManagerDataSource'>
<property name='driverClassName'>
<value>${database.driver}</value>
</property>
<property name='url'>
<value>${database.uri}</value>
</property>
<property name='username'>
<value>${database.user}</value>
</property>
<property name='password'>
<value>${database.password}</value>
</property>
</bean>
…无论是测试还是现场直播,您只要写:
<jee:jndi-lookup id='dataSource' jndi-name='jdbc/LiveDataSource'/>
Spring准则指出,仅应在上面的第二个示例中使用Spring概要文件:特定于Bean的类,并且您应继续使用PropertyPlaceholderConfigurer初始化简单的Bean属性; 但是,您可能希望使用Spring配置文件将特定于环境的PropertyPlaceholderConfigurer注入到Spring上下文中。
话虽如此,我将在示例代码中打破这一约定,因为我想用最简单的代码来演示Spring配置文件的功能。
Spring配置文件和XML配置
在XML配置方面,Spring 3.1在spring-beans模式的bean元素中引入了新的profile属性:
<beans profile='dev'>
在不同环境中启用和禁用配置文件时,此配置文件属性充当开关。
为了进一步解释所有这些,我将使用一个简单的想法,即您的应用程序需要加载一个人员类,并且该人员类包含不同的属性,具体取决于您的程序在其上运行的环境。
Person类非常简单,看起来像这样:
public class Person {
private final String firstName;
private final String lastName;
private final int age;
public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public int getAge() {
return age;
}
}
…并在以下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'
xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd'
profile='test1'>
<bean id='employee' class='profiles.Person'>
<constructor-arg value='John' />
<constructor-arg value='Smith' />
<constructor-arg value='89' />
</bean>
</beans>
…和
<?xml version='1.0' encoding='UTF-8'?>
<beans xmlns='http://www.springframework.org/schema/beans'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd'
profile='test2'>
<bean id='employee' class='profiles.Person'>
<constructor-arg value='Fred' />
<constructor-arg value='ButterWorth' />
<constructor-arg value='23' />
</bean>
</beans>
…分别称为test-1-profile.xml和test-2-profile.xml (请记住这些名称,它们在以后很重要)。 如您所见,配置的唯一区别是名字,姓氏和年龄属性。
不幸的是,仅仅定义个人资料还不够,您必须告诉Spring您正在加载哪个个人资料。 这意味着遵循旧的“标准”代码现在将失败:
@Test(expected = NoSuchBeanDefinitionException.class)
public void testProfileNotActive() {
// Ensure that properties from other tests aren't set
System.setProperty('spring.profiles.active', '');
ApplicationContext ctx = new ClassPathXmlApplicationContext('test-1-profile.xml');
Person person = ctx.getBean(Person.class);
String firstName = person.getFirstName();
System.out.println(firstName);
}
幸运的是,有几种选择配置文件的方法,在我看来,最有用的方法是使用“ spring.profiles.active”系统属性。 例如,以下测试现在将通过:
System.setProperty('spring.profiles.active', 'test1');
ApplicationContext ctx = new ClassPathXmlApplicationContext('test-1-profile.xml');
Person person = ctx.getBean(Person.class);
String firstName = person.getFirstName();
assertEquals('John', firstName);
显然,您不想像我上面那样对代码进行硬编码,最佳实践通常意味着将系统属性定义与应用程序分开。 这使您可以选择使用简单的命令行参数,例如:
-Dspring.profiles.active='test1'
…或通过添加
# Setting a property value
spring.profiles.active=test1
Tomcat的catalina.properties
因此,仅此而已:您可以使用bean元素配置文件属性创建Spring XML配置文件,并通过将spring.profiles.active系统属性设置为配置文件的名称来打开要使用的配置文件 。
获得一些额外的灵活性
但是,这还不是故事的结局,因为Spring的Guy已添加了许多以编程方式加载和启用配置文件的方式-如果您愿意的话。
@Test
public void testProfileActive() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
'test-1-profile.xml');
ConfigurableEnvironment env = ctx.getEnvironment();
env.setActiveProfiles('test1');
ctx.refresh();
Person person = ctx.getBean('employee', Person.class);
String firstName = person.getFirstName();
assertEquals('John', firstName);
}
在上面的代码中,我使用了新的ConfigurableEnvironment类来激活“ test1”配置文件。
@Test
public void testProfileActiveUsingGenericXmlApplicationContextMultipleFilesSelectTest1() {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ConfigurableEnvironment env = ctx.getEnvironment();
env.setActiveProfiles('test1');
ctx.load('*-profile.xml');
ctx.refresh();
Person person = ctx.getBean('employee', Person.class);
String firstName = person.getFirstName();
assertEquals('John', firstName);
}
但是,Spring专家们建议您使用GenericApplicationContext类而不是ClassPathXmlApplicationContext和FileSystemXmlApplicationContext,因为这样可以提供更大的灵活性。 例如,在上面的代码中,我已经使用GenericApplicationContext的load(...)方法使用通配符来加载许多配置文件:
ctx.load('*-profile.xml');
还记得以前的文件名吗? 这将同时加载test-1-profile.xml和test-2-profile.xml 。
配置文件还具有额外的灵活性,可让您一次激活多个。 如果看下面的代码,您会看到我正在激活我的test1和test2配置文件:
@Test
public void testMultipleProfilesActive() {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ConfigurableEnvironment env = ctx.getEnvironment();
env.setActiveProfiles('test1', 'test2');
ctx.load('*-profile.xml');
ctx.refresh();
Person person = ctx.getBean('employee', Person.class);
String firstName = person.getFirstName();
assertEquals('Fred', firstName);
}
请注意,在本示例中,我有两个ID为“ employee”的bean,并且无法分辨哪个是有效的,并且应该优先。 从我的测试中,我猜想读取的第二个将覆盖或屏蔽对第一个的访问。 没关系,因为您不应该拥有多个具有相同名称的bean –激活多个配置文件时需要提防。
最后,可以做的更好的简化之一是使用嵌套的<beans />元素。
<?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-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd'>
<beans profile='test1'>
<bean id='employee1' class='profiles.Person'>
<constructor-arg value='John' />
<constructor-arg value='Smith' />
<constructor-arg value='89' />
</bean>
</beans>
<beans profile='test2'>
<bean id='employee2' class='profiles.Person'>
<constructor-arg value='Bert' />
<constructor-arg value='William' />
<constructor-arg value='32' />
</bean>
</beans>
</beans>
尽管以最小的灵活性为代价,但是这消除了通配符和加载多个文件的所有繁琐处理。
我的下一个博客通过查看与新的@Profile注释结合使用的@Configuration注释,总结了我对Spring概要文件的了解,因此,稍后会有更多介绍。
参考:来自Captain Debug博客博客的JCG合作伙伴 Roger Hughes提供的在XML Config中使用Spring Profiles 。
翻译自: https://www.javacodegeeks.com/2012/08/spring-profiles-in-xml-config-files.html
spring配置xml文件