В 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.