开发中遇到的最大挑战之一,是环境的变化。数据库配置、加密算法以及与外部系统的集成等都和开发环境相关。
# 编译时定义bean
以数据库为例,在开发的时候,会倾向于使用测试数据,比如在Spring的配置类里,可能会像下面这样配置EmbeddedDatabaseBuilder(),以创建一个DataSource的bean:
这样,在开发环境中,可以根据需要,在schema.sql和test-data.sql中增加模拟数据。生产环境不能这么做,而更倾向于使用JNDI,创建一个DataSource的bean:
使用JNDI,容器可以决定怎样创建DataSource,包括从连接池中交接DataSource。当然,这些对生产环境很有用,但对开发情况下的测试以及简单的集成测试来说,一般并不需要。
而QA环境可能想用另外的配置:
可以使用例如Maven profiles的方式,在不同环境进行重新编译(build)来解决和环境相关的问题,但是,重新build可能引入新的bug,而这是灾难性的。
# 运行时生成bean
Spring的方案和上述方案差不多,只是改成了运行时配置。生产环境和开发环境使用同一套代码,避免在发布时,因为更改java代码,重新编译代码引起问题。可以在方法或类上加Profile标签,这样,只有环境满足条件时,才会生成相应的bean,而没有加这个标签的bean是在任何条件下都会生成的。
也可以使用XML做到这一点,本笔记略。
Profile 标签的定义如下:
可以看出,Profile标签是运行时生效,并且支持标注在类和方法上,同时,被@Conditional标注,表明只有满足ProfileCondition条件时,才生效。ProfileCondition定义如下:
可以看出,判断是否匹配的逻辑是,从@Profile标签中获取可接受的Profile值列表(可以有多个值),再从上下文中获取环境,判断环境中当前是否包含这些Profile值,以判断当前环境是否满足条件。那么,如何在环境中设置当前Profile值呢?
# 在环境中设置当前Profile
Spring使用spring.profiles.active和spring.profiles.default属性来确定当前Profile。spring.profiles.active不为空时,spring.profiles.active的值是当前Profile,spring.profiles.active的值为空时,spring.profiles.default的值是当前Profile,两个都为空时,则所有加了Profile标签的bean都不生成,没有加Profile标签的bean才会生成。可以使用以下方式设置这两个属性:
* 作为DispatcherServlet的参数
* 作为web应用上下文的参数
* 作为JNDI的entry
* 作为环境变量
* 作为JVM系统属性
* 在一个集成测试类上使用@ActiveProfiles标签
你可以自己选择最合适的方式。
# 测试Profile以指定环境
当代码里使用了Profile来指定环境相关的操作后,有时候需要在测试环境中模拟与生产环境相同的Profile,来进行测试。Spring提供了@ActiveProfiles标签,指定测试程序运行时的当前Profile。下面,在添加开发环境配置初始化sql文件schema.sql和test-data.sql后,以及上文中的DataSourceConfig的配置类后,进行数据库测试(这些代码都可以在[官方样例](
https://manning-content.s3.amazonaws.com/download/9/ef4e0ef-b7bd-4ab8-857d-eb635d18d425/SpringiA4_SourceCode.zip)下载)。
schema.sql如下:
test-data.sql如下:
测试代码如下:
可以看到,开发环境的dataSource生成成功,并且能够正确的查询数据。而生产环境由于没有在JNDI中配置数据库,dataSource为空。
读到了这里,给自己点一个赞吧(^_^) 如果您喜欢这篇文章,可以考虑收藏和分享给更多朋友哦,在此拜谢orz!偷偷告诉您一个小秘密:收藏和分享后,在PC上看IT文章,观感更好哦。您可以在浏览器输入toutiao.com访问今日头条,也可以直接访问我的独立博客tantanit.com。这篇文章的地址是
http://tantanit.com/springinacton4-du-shu-bi-ji-zhi-gen-ju-kai-fa-huan-jing-zhuang-pei-bean/
声明:本站部分文章内容及图片转载于互联 、内容不代表本站观点,如有内容涉及侵权,请您立即联系本站处理,非常感谢!