zoukankan      html  css  js  c++  java
  • Spring 3.1 Environment Profiles--转载

    原文地址:http://gordondickens.com/wordpress/2012/06/12/spring-3-1-environment-profiles/

    Profiles

    Spring 3.1 now includes support for the long awaited environment aware feature called profiles. Now we can activate profiles in our application, which allows us to define beans by deployment regions, such as “dev”, “qa”, “production”, “cloud”, etc.

    We also can use this feature for other purposes: defining profiles for performance testing scenarios such as “cached” or “lazyload”.

    Essential Tokens

    Spring profiles are enabled using the case insensitive tokens spring.profiles.active orspring_profiles_active.

    This token can be set as:

    • an Environment Variable
    • a JVM Property
    • Web Parameter
    • Programmatic

    Spring also looks for the token, spring.profiles.default, which can be used to set the default profile(s) if none are specified with spring.profiles.active.

    Grouping Beans by Profile

    Spring 3.1 provides nested bean definitions, providing the ability to define beans for various environments:

    1
    2
    3
    4
    <beans profiles="dev,qa">
      <bean id="dataSource" class="..."/>
      <bean id="messagingProvider" class="..."/>
    </beans>

    Nested <beans> must appear last in the file. 
    Beans that are used in all profiles are declared in the outer <beans> as we always have, such as Service classes.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <?xml version="1.0" encoding="UTF-8"?>
           xsi:schemaLocation="http://www.springframework.org/schema/beans
     
        <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>

    If we put a single <bean> declaration at below any nested <beans> tags we will get the exception org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'bean'.

    Multiple beans can now share the same XML “id” 
    In a typical scenario, we would want the DataSource bean to be called dataSource in both all profiles. Spring now allow us to create multiple beans within an XML file with the same ID providing they are defined in different <beans> sets. In other words, ID uniqueness is only enforced within each <beans> set.

    Automatic Profile Discovery (Programmatic)

    We can configure a class to set our profile(s) during application startup by implementing the appropriate interface. For example, we may configure an application to set different profiles based on where the application is deployed – in CloudFoundry or running as a local web application. In the web.xml file we can include an Servlet context parameter,contextInitializerClasses, to bootstrap this class:

    1
    2
    3
    4
    <context-param>
      <param-name>contextInitializerClasses</param-name>
      <param-value>com.gordondickens.springthreeone.services.CloudApplicationContextInitializer</param-value>
    </context-param>

    The Initializer class

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    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");
        }
      }
    }

    Annotation Support for JavaConfig

    If we are are using JavaConfig to define our beans, Spring 3.1 includes the @Profileannotation for enabling bean config files by profile(s).

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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;
      }
    }

    Testing with XML Configuration

    With XML configuration we can simply add the annotation @ActiveProfiles to the JUnit test class. To include multiple profiles, use the format @ActiveProfiles(profiles = {"dev", "prod"})

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    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);
      }
    }

    Testing with JavaConfig

    JavaConfig allows us to configure Spring with or without XML configuration. If we want to test beans that are defined in a Configuration class we configure our test with the loaderand classes arguments of the @ContextConfiguration annotation.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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);
      }
    }

    Declarative Configuration in WEB.XML

    If we desire to set the configuration in WEB.XML, this can be done with parameters onContextLoaderListener.

    Application Context

    1
    2
    3
    4
    5
    6
    7
    8
    <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>

    Log Results

    DEBUG PropertySourcesPropertyResolver - Found key 'spring.profiles.active' in [servletContextInitParams] with type [String] and value 'DOUBLEUPMINT'

    Environment Variable/JVM Parameter
    Setting an environment variable can be done with either spring_profiles_default orspring_profiles_active. In Unix/Mac it would be export SPRING_PROFILES_DEFAULT=DEVELOPMENT for my local system.

    We can also use the JVM “-D” parameter which also works with Maven when using Tomcat or Jetty plugins.

    Note: Remember the tokens are NOT case sensitive and can use periods or underscores as separators. For Unix systems, you need to use the underscore, as above.

    Logging of system level properties DEBUG PropertySourcesPropertyResolver - Found key 'spring.profiles.default' in [systemProperties] with type [String] and value 'dev,default'

    Summary

    Now we are equipped to activate various Spring bean sets, based on profiles we define. We can use  traditional, XML based configuration, or the features added to support JavaConfig originally introduced in Spring 3.0.

  • 相关阅读:
    JSON操作技巧
    我的前端学习历程(转)
    sql指南网址
    using 和try/catch区别和注意点
    【转】StringBuffer的用法与string的区别
    【转】比较page、request、session、application的使用范围
    【转】StringBuilder用法
    【转】.Net高级技术——IDisposable
    【转】.NET快速查找某个类所在的命名空间
    【转】VS2010安装包制作
  • 原文地址:https://www.cnblogs.com/davidwang456/p/4429058.html
Copyright © 2011-2022 走看看