В Spring 3.1 теперь включена поддержка долгожданной среды, которая называется профили. Теперь мы можем активировать профили в нашем приложении, что позволяет нам определять компоненты по областям развертывания, таким как «dev», «qa», «production», «cloud» и т. Д.
Мы также можем использовать эту функцию для других целей: определения профилей для сценариев тестирования производительности, таких как «кэшированный» или «lazyload».
Основные токены
Профили Spring включаются с использованием нечувствительных к регистру токенов spring.profiles.active или spring_profiles_active.
Этот токен может быть установлен как:
- переменная среды
- Свойство JVM
- Веб-параметр
- программный
Spring также ищет токен, spring.profiles.default, который можно использовать для установки профилей по умолчанию, если ни один из них не указан в spring.profiles.active.
Группировка бобов по профилю
Spring 3.1 предоставляет определения вложенных bean-компонентов, предоставляя возможность определять bean-компоненты для различных сред:
<beans profiles="dev,qa"> <bean id="dataSource" class="..."/> <bean id="messagingProvider" class="..."/> </beans>
Вложенные <beans> должны появляться последними в файле.
Бины, используемые во всех профилях, объявляются во внешнем <beans>, как мы всегда это делаем, например, в классах Service.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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.xsd">
<bean id="businessService"
class="com.c...s.springthreeone.business.SimpleBusinessServiceImpl"/>
<beans profile="dev,qa">
<bean id="constructorBean"
class="com.gordondickens.springthreeone.SimpleBean"
c:myString="Constructor Set"/>
<bean id="setterBean"
class="com.gordondickens.springthreeone.SimpleBean">
<property name="myString" value="Setter Set"/>
</bean>
</beans>
<beans profile="prod">
<bean id="setterBean"
class="com.gordondickens.springthreeone.SimpleBean">
<property name="myString" value="Setter Set - in Production YO!"/>
</bean>
</beans>
</beans>
Если мы поместим одно объявление <bean> ниже любых вложенных тегов <beans>, мы получим исключение org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: было найдено недопустимое содержимое, начиная с элемента ‘bean’ ,
Теперь несколько бинов могут совместно использовать один и тот же «идентификатор» XML.
В типичном сценарии мы бы хотели, чтобы бин DataSource назывался dataSource во всех всех профилях. Spring теперь позволяет нам создавать несколько bean-компонентов внутри XML-файла с одним и тем же идентификатором при условии, что они определены в разных наборах <beans>. Другими словами, уникальность идентификатора применяется только в каждом наборе <beans>.
Автоматическое обнаружение профиля (программный)
Мы можем настроить класс для установки наших профилей во время запуска приложения путем реализации соответствующего интерфейса. Например, мы можем настроить приложение для установки различных профилей в зависимости от того, где приложение развернуто — в CloudFoundry или в качестве локального веб-приложения. В файле web.xml мы можем включить параметр контекста сервлета contextInitializerClasses, чтобы загрузить этот класс:
<context-param> <param-name>contextInitializerClasses</param-name> <param-value>com.gordondickens.springthreeone.services.CloudApplicationContextInitializer</param-value> </context-param>
Класс Initializer
package com.gordondickens.springthreeone.services;
import org.cloudfoundry.runtime.env.CloudEnvironment;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
public class CloudApplicationContextInitializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final Logger logger = LoggerFactory
.getLogger(CloudApplicationContextInitializer.class);
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
CloudEnvironment env = new CloudEnvironment();
if (env.getInstanceInfo() != null) {
logger.info("Application running in cloud. API '{}'",
env.getCloudApiUri());
applicationContext.getEnvironment().setActiveProfiles("cloud");
applicationContext.refresh();
} else {
logger.info("Application running local");
applicationContext.getEnvironment().setActiveProfiles("dev");
}
}
}
Поддержка аннотаций для JavaConfig
Если мы используем JavaConfig для определения наших bean-компонентов, Spring 3.1 включает аннотацию @Profile для включения конфигурационных файлов bean-компонентов по профилям.
package com.gordondickens.springthreeone.configuration;
import com.gordondickens.springthreeone.SimpleBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("dev")
public class AppConfig {
@Bean
public SimpleBean simpleBean() {
SimpleBean simpleBean = new SimpleBean();
simpleBean.setMyString("Ripped Pants");
return simpleBean;
}
}
Тестирование с настройкой XML
С помощью конфигурации XML мы можем просто добавить аннотацию @ActiveProfiles в тестовый класс JUnit. Чтобы включить несколько профилей, используйте формат @ActiveProfiles (profile = {«dev», «prod»})
package com.gordondickens.springthreeone;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@ActiveProfiles(profiles = "dev")
public class DevBeansTest {
@Autowired
ApplicationContext applicationContext;
@Test
public void testDevBeans() {
SimpleBean simpleBean =
applicationContext.getBean("constructorBean", SimpleBean.class);
assertNotNull(simpleBean);
}
@Test(expected = NoSuchBeanDefinitionException.class)
public void testProdBean() {
SimpleBean prodBean = applicationContext.getBean("prodBean", SimpleBean.class);
assertNull(prodBean);
}
}
Тестирование с JavaConfig
JavaConfig позволяет нам конфигурировать Spring с настройкой XML или без нее. Если мы хотим протестировать bean-компоненты, определенные в классе Configuration, мы конфигурируем наш тест с аргументами загрузчика и классов аннотации @ContextConfiguration.
package com.gordondickens.springthreeone.configuration;
import com.gordondickens.springthreeone.SimpleBean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import static org.junit.Assert.assertNotNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class, loader = AnnotationConfigContextLoader.class)
@ActiveProfiles(profiles = "dev")
public class BeanConfigTest {
@Autowired
SimpleBean simpleBean;
@Test
public void testBeanAvailablity() {
assertNotNull(simpleBean);
}
}
Декларативная конфигурация в WEB.XML
Если мы хотим установить конфигурацию в WEB.XML, это можно сделать с помощью параметров в ContextLoaderListener.
Контекст приложения
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/app-config.xml</param-value> </context-param> <context-param> <param-name>spring.profiles.active</param-name> <param-value>DOUBLEUPMINT</param-value> </context-param>
Результаты журнала
DEBUG PropertySourcesPropertyResolver — Найден ключ «spring.profiles.active» в [servletContextInitParams] с типом [String] и значением «DOUBLEUPMINT»
Переменная среды / параметр JVM
Установка переменной среды может быть выполнена с помощью spring_profiles_default или spring_profiles_active. В Unix / Mac это будет экспорт SPRING_PROFILES_DEFAULT = DEVELOPMENT для моей локальной системы.
Мы также можем использовать параметр «-D» JVM, который также работает с Maven при использовании плагинов Tomcat или Jetty.
Примечание. Помните, что токены НЕ чувствительны к регистру и могут использовать точки или подчеркивания в качестве разделителей. Для систем Unix вам нужно использовать подчеркивание, как указано выше.
Регистрация свойств системного уровня
Резюме
Теперь у нас есть возможность активировать различные наборы Spring bean на основе определенных нами профилей. Мы можем использовать традиционную конфигурацию на основе XML или функции, добавленные для поддержки JavaConfig, первоначально представленного в Spring 3.0.