博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring的条件装配bean
阅读量:4542 次
发布时间:2019-06-08

本文共 2555 字,大约阅读时间需要 8 分钟。

1 应用程序环境的迁移

问题:

开发软件时,有一个很大的挑战,就是将应用程序从一个环境迁移到另一个环境。

例如,开发环境中很多方式的处理并不适合生产环境,迁移后需要修改,这个过程可能会莫名的出现很多bug,一个经常出现在程序员间有意思的问题是:在我那明明没问题啊,为什么到你那就不行了?

举个栗子,数据库配置,在开发环境我们可能使用一个嵌入式的数据源并在启动的时候加载进来,但是在生产环境中这是糟糕的做法,我们希望数据库能直接从JNDI中获取,或者是从连接池中获取。那么问题来了,当从开发环境迁移到生产环境中时,我们应该怎么做?

一个很好想到的办法是:配置多个xml文件,每个xml里面配置一种数据源。然后在构建阶段,确定哪一种数据源编译到可部署的应用中。

但是这样的做法缺点要为每种环境重新构建应用,从开发阶段迁移到QA(质量保证)阶段肯能没什么大问题,但是从QA迁移到生产阶段从新构建可能会出现bug,还QA个毛啊~

解答:

Spring为环境迁移提供的解决方案是profile功能,为bean配置profile注解,然后激活对应的profile。

怎么配置profile?下面有两种方式:

(1)基于Java配置

@Configurationpublic class DataSourceConfig {    @Bean    @Profile("dev")    public DataSource embeddedDataSource() {        // 配置开发环境     嵌入式数据源            }    @Bean    @Profile("prod")    public DataSource jndiDataSource() {        // 配置生产环境    JNDI数据源            }}

(2)基于xml配置

怎么激活profile?

Spring在确定哪个profile处于激活状态时,需要依赖两个独立的属性:spring.profiles.active和spring.profiles.default。

如果设置了spring.profiles.active属性的话,那么它的值就会用来确定哪个profile是激活的。但如果没有设置spring.profiles.active,那Spring将会查找spring.profiles.default的值。如果两个属性都没配置,那么被@Profile注解的类都不会被加载。

有多种方式来设置这两个属性:

  • 作为DispatcherServlet的初始化参数;
  • 作为Web应用的上下文参数;
  • 作为JNDI条目;
  • 作为环境变量;
  • 作为JVM的系统属性;
  • 在集成测试类上,使用@ActiveProfiles注解设置。

如何配置这些初始化参数不是本文讨论的内容。但为了把例子解释清楚,这里以web应用上下文参数为例梳理整个流程,配置如下:

这里默认激活配置为dev的profile,所以启动应用时,以Java配置为例,注解@Profile("dev")标记的数据库连接类会被加载到spring容器中,@Profile("prod")标记的类不会被加载。

profile是spring3.1中出现的新功能,只能用于环境迁移的条件装配,但是spring4引入了Conditional功能,我们能灵活的处理条件化装配bean了,而且spring4也使用Conditional重构了profile,也就是说spring4之后,prefile是基于Conditional实现的。

 

 

2 条件装配bean

假如你希望一个或多个bean只有在应用的类路径下包含特定的库时才创建。或者我们希望某个bean只有当另外某个特定的bean也声明了之后才会创建。我们还可能要求只有某个特定的环境变量设置之后,才会创建某个bean。这些使用Conditional都能实现。

举个例子:假设有一个名为MagicBean的类,我们希望只有设置了magic环境属性的时候,Spring才会实例化这个类。如果环境中没有这个属性,那么MagicBean将会被忽略。

首先要有一个MagicBean,我们不关注它的功能与实现,只需要知道有这个bean就行。接下来配置:

 

@Configurationpublic class MagicConfig {  @Bean  @Conditional(MagicExistsCondition.class)  public MagicBean magicBean() {    return new MagicBean();  }  }

 

只有满足MagicExistsCondition这个条件时,我们才实例化MagicBean。MagicExistsCondition需要实现Condition接口。Condition接口里面只有matches()方法,当实现类的matches()返回true时,条件才满足。否则条件不满足。MagicExistsCondition实现如下:

 

public class MagicExistsCondition implements Condition {  @Override  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {    Environment env = context.getEnvironment();    return env.containsProperty("magic");  }  }

 

只有环境变量magic存在,matches才会返回true,条件才满足,MagicBean才会实例化。

 

转载于:https://www.cnblogs.com/exmyth/p/11304533.html

你可能感兴趣的文章
数值分析清考给弄纠结了
查看>>
转:GestureDetector: GestureDetector 基本使用
查看>>
小顶堆第二弹-----堆降序排序(C语言非递归)
查看>>
我的一年学习之路
查看>>
mysql优化问题汇总
查看>>
ajax asud模板
查看>>
初识java
查看>>
敏捷、瀑布开发模式
查看>>
类的初始化顺序
查看>>
HDU 2040 亲和数 [补] 分类: ACM 2...
查看>>
实习日记)select option 选择不同的option时, 页面发生不同的变化
查看>>
Keywords Search HDU2222 AC自动机模板题
查看>>
浅谈TCP/IP网络编程中socket的行为
查看>>
从上向下打印二叉树
查看>>
计算机日语
查看>>
04-关键字、标识符、注释
查看>>
01-HTML基础与进阶-day4-录像247
查看>>
mysql表操作
查看>>
Flask Web开发从入门到放弃(一)
查看>>
数组的完全随机排列
查看>>