开发和生产环境的动态配置问题

我们在编程的时候,难免需要不断的在开发和生产环境进行切换,这过程我们的数据库连接和缓存的配置等都很可能不一样,例如生产我们用的是MenCache做缓存的,开发环境是用的是Redis,这需要我么来切换,手动切换是很忌讳的,因为手工总是不靠谱的,难免会忘记切换了,我们需要的是自动化的方式,对此我们可以用两种方式来解决

  1. @Profile
  2. @Conditonal

例子如下

@profile登场

看一下关于profile的简单演示

@Configuration 
public class DataSourceConfig {

    @Bean
    @Profile("dev")
    public BaseCache redisCache() {
        return new RedisCache();
    }

    @Bean
    @Profile("product")
    public BaseCache menCache() {
        return new MenCache();
    }    
}  

这两个bean不会被注册,除非我们激活他们
激活的方式很多,下面提供一种常见的

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("dev");
ctx.register(DataSourceConfig.class);
ctx.refresh();

这样我们就可以用所有profile是dev的bean了。
另外,在测试环境,spring提供了一个ActiveProfiles, 具体的使用如下

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DataSourceConfig.class)
@ActiveProfiles("dev")
public class ConditionalTest {


    @Test
    public void testProfiles() {        
        BaseCache baseCache = context.getBean(BaseCache.class);        
        if (baseCache != null) {
            System.out.println(" cache name =" + baseCache.getCacheName());
        } 
    }

}

当然,这个还是不够自动化,仍然需要我们去手动的控制这个我们到底选中的是哪一个bean;
为此,我们推荐一个新的东东,叫@Conditoanl


@Conditonal登场

啥也不说,先show you the code!

@Configuration
public class DataSourceConfig {

    @Bean
    @Conditional(ProductExistsCondition.class)
    public BaseCache redisCache() {
        return new RedisCache();
    }

    @Bean
    @Conditional(DevExistsCondition.class)
    public BaseCache menCache() {
        return new MenCache();
    }

}

这些bean都被赋予了一个条件类,当这个条件类返回真的时候,这个bean就会被激活;
来看下ProductExistsCondition是怎样的

public class ProductExistsCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        System.out.println("matching");

        String profile = System.getProperty("profile").toLowerCase();
        System.out.println(" profile name="+profile);
        return !profile.startsWith("product");
    }

}

再来看下这个开发环境下的条件类

public class DevExistsCondition implements Condition {

        @Override
        public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
            System.out.println("matching");

            String profile = System.getProperty("profile").toLowerCase();
            System.out.println(" profile name="+profile);
            return !profile.startsWith("dev");
        }

}

我们的条件类事实现了spring提供的Conditon接口的,然后供spirng调用,这个接口返回为真,则激活该bean,为false则不激活。另外我们设置系统的属性里面加多一个叫“profile”的环境变量,这样我们就可以全自动的切换到不同的环境去,只要我们在系统的环境变量里面加多了一个profile的属性。并将他的值设置成了dev,那么这台电脑就是开发环境下的。

热评文章