spring中存在这样一个功能,通过Profile来选择不同环境下的不同配置,说白了,就是通过设置一个参数来选择使用不同的数据,这个数据可能是一个bean,可能是一个xml文件,也有可能是一个propertes文件。

经过代码演练和测试,我大体知道了这个功能是干嘛的,也初步知道了它的几种实现方式,但是实际上我依然不是十分明白它的优势和好处在何处,因为根据自己以往的项目经验来说,我觉得用这种方式似乎还有点把简单功能复杂化了。

只是,在网络上我不止一次看到过它,似乎很多人都在用。因此我觉得还是了解一下、学习一下为好,或许它的好处只是我暂时不清楚,而不代表这个好处不存在。

为了让刚接触的朋友能更好的理解,我这里基本上都是代码和测试都写出来,并且三种方式简单的对比,以便于在大家需要用到的时候能具体场景下具体的选择。

实现方式一

完全的java代码加注解的方式,首先创建一个简单的带有构造方法和get、set方法的类:

  1. package springTest4;
  2. public class ProFileTest {
  3. private String msg;
  4. public ProFileTest(String msg) {
  5. super();
  6. this.msg = msg;
  7. }
  8. public String getMsg() {
  9. return msg;
  10. }
  11. public void setMsg(String msg) {
  12. this.msg = msg;
  13. }
  14. public void printTest() {
  15. System.out.println(msg);
  16. }
  17. }

然后再创建一个相当于spring中xml配置文件的类,并且使用注解把这个类声明成一个配置类,同时把上边的类声明为一个bean,并制定profile名称(也就是上边说的profile的选择参数):

  1. package springTest4;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.context.annotation.Profile;
  5. @Configuration
  6. public class ProFileConf {
  7. @Bean
  8. @Profile("test1")
  9. public ProFileTest proTest1() {
  10. return new ProFileTest("test11111");
  11. }
  12. @Bean
  13. @Profile("test2")
  14. public ProFileTest proTest2() {
  15. return new ProFileTest("test22222");
  16. }
  17. }

这里的@Configuration即声明这个类是一个相当于spring中xml的配置类,剩下两个在前一段文字描述中已经说了,就不再赘述。

至于这段代码的解释,我想通过下边调用的测试代码之后再做解释,模拟profile调用的main方法如下:

  1. package springTest4;
  2. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  3. public class MainPro {
  4. public static void main(String[] args) {
  5. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  6. context.getEnvironment().setActiveProfiles("test2");
  7. context.register(ProFileConf.class);
  8. context.refresh();
  9. String mString = context.getBean(ProFileTest.class).getMsg();
  10. System.out.println(mString);
  11. context.close();
  12. }
  13. }

这里的new AnnotationConfigApplicationContext()声明一个空的上下文,我想学过spring的应该都不需要解释。

context.getEnvironment().setActiveProfiles(“test2”)的意思是获取环境变量,或者理解成获取配置数据,然后把活动的profile的参数或者说名称设置成test2。

context.register(ProFileConf.class)注册具体的配置文件,这里就是ProFileCon.class。

然后后边的几行代码分别是刷新上下文,获取具体的bean对象等等,这些就是比较常规的操作了。

上面的方法执行后结果如图:



而当我把context.getEnvironment().setActiveProfiles(“test2”)这里的test2设置成test1的时候,结果就会成为test11111。

那么结合上边的ProFileConf 中的代码,我想就比较容易理解了,也就是说这里配置了profile参数后,当我们把activeProfiles设置成某个参数时,spring在加载时便会调用这个参数对应的profile的内容。

但是为什么我要说看不出来这样使用的好处在哪里呢?是因为我觉得就这个例子来说,完全可以直接在创建新的对象时用构造方法的不同参数来实现。

当然了,这只是个为了说明这项功能的例子,实际使用自然不会这样,实际使用的时候,可能是用来加载不同的配置文件里的值和属性,也可能是用来调用不同的配置文件。

只不过,即便是这样,我依旧觉得也都可以用参数的方式实现,似乎没有必要这样绕来绕去,并没看到怎么简化了开发,也没看到有什么性能上的提升。

那么还有实现方式二

这个方式和上边的其实是类似的,因为唯一的不同在于把起xml配置文件作用的java类实打实的变成xml配置,因为使用的有构造方法和get、set方法的类是同一个,因此就不再重复贴出来,这里就从test1.xml开始:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <beans profile="test1">
  7. <bean id="proTest1" class="springTest4.ProFileTest">
  8. <constructor-arg name="msg" value="test11111" />
  9. </bean>
  10. </beans>
  11. <beans profile="test2">
  12. <bean id="proTest2" class="springTest4.ProFileTest">
  13. <constructor-arg name="msg" value="test22222" />
  14. </bean>
  15. </beans>
  16. </beans>

这也是一个极其简单的spring配置,除开必要的文件头尾,就只有两个几乎一模一样的beans,指定了profile名称,以及内部的一个普通bean,这个bean以构造函数注入。

对于这种写法,调用也基本是一样的,只不过context获取的是xml而不是calss:

  1. package springTest4;
  2. import org.springframework.context.support.ClassPathXmlApplicationContext;
  3. public class MainPro {
  4. public static void main(String[] args) {
  5. ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("test1.xml");
  6. context.getEnvironment().setActiveProfiles("test2");
  7. context.refresh();
  8. String mString = context.getBean(ProFileTest.class).getMsg();
  9. System.out.println(mString);
  10. context.close();
  11. }
  12. }

至于这里的具体说明,我想通过对第一个例子的解释,应该已经没有必要再多说了。

实现方式三

前边两种方式,根本上来说是改变了profile的声明方式,而这里需要变得则是调用方式,前两个抛开细节来说,都是在java类中调用,而这里则是在web.xml中调用,当然了,既然有web.xml文件,自然也要是一个web项目才行,web.xml文件配置如下:

  1. <!DOCTYPE web-app PUBLIC
  2. "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  3. "http://java.sun.com/dtd/web-app_2_3.dtd" >
  4. <web-app>
  5. <display-name>Archetype Created Web Application</display-name>
  6. <servlet>
  7. <servlet-name>dispatcher</servlet-name>
  8. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  9. <init-param>
  10. <param-name>contextConfigLocation</param-name>
  11. <param-value>classpath:test1.xml</param-value>
  12. </init-param>
  13. <init-param>
  14. <param-name>spring.profiles.default</param-name>
  15. <param-value>test2</param-value>
  16. </init-param>
  17. <load-on-startup>1</load-on-startup>
  18. </servlet>
  19. <servlet-mapping>
  20. <servlet-name>dispatcher</servlet-name>
  21. <url-pattern>/</url-pattern>
  22. </servlet-mapping> >
  23. </web-app>

这个web.xml也是一个只为了说明profile的文件,只要一个selvlet配置,两个init-param,第一个是指定自定义的dispatcher-servlet.xml,如果不指定,启动tomcat的时候就会出现如下的错误:

  1. org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from ServletContext resource [/WEB-INF/dispatcher-servlet.xml]; nested exception is java.io.FileNotFoundException: Could not open ServletContext resource [/WEB-INF/dispatcher-servlet.xml]
  2. at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:343)
  3. at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:303)
  4. at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:180)

而第二个init-param则是指定默认的profile的名称。

为了测试这种方式是否可行,我在第二种方式的基础上略作了修改,java类中加入了一个init-method方法,修改之后对应的java类和xml配置如下:

  1. package springTest4;
  2. public class ProFileTest {
  3. private String msg;
  4. public ProFileTest(String msg) {
  5. super();
  6. this.msg = msg;
  7. }
  8. public String getMsg() {
  9. return msg;
  10. }
  11. public void setMsg(String msg) {
  12. this.msg = msg;
  13. }
  14. public void printTest() {
  15. System.out.println(msg);
  16. }
  17. }
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans
  5. http://www.springframework.org/schema/beans/spring-beans.xsd">
  6. <beans profile="test1">
  7. <bean id="proTest1" class="springTest4.ProFileTest" init-method="printTest">
  8. <constructor-arg name="msg" value="test11111" />
  9. </bean>
  10. </beans>
  11. <beans profile="test2">
  12. <bean id="proTest2" class="springTest4.ProFileTest" init-method="printTest">
  13. <constructor-arg name="msg" value="test22222" />
  14. </bean>
  15. </beans>
  16. </beans>

启动tomcat的过程中,控制台也打印出了预想中的数据,证明第三种方式也是可行的。

以上便是我所知道的三种profile的实现方式,至于具体应用场景,我虽然知道主要是为了方便各种不同环境的切换。比如生产一套配置,测试一套配置;再比如一套单机环境,一套集群环境等等,但是我都觉得完全可以在部署的时候,在spring的context:property-placeholder以及import resource的时候切换。

而且这种切换比起profile来说似乎更加容易上手,所以就不太明白profile的优势究竟在于哪里,欢迎朋友们留言解惑。

spring的Profile使用对比和应用场景分析的更多相关文章

  1. 【译】Spring 4 @Profile注解示例

    前言 译文链接:http://websystique.com/spring/spring-profile-example/ 本文将探索Spring中的@Profile注解,可以实现不同环境(开发.测试 ...

  2. Spring Cloud介绍 Spring Cloud与Dubbo对比

    spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集群状 ...

  3. 【转】Spring Boot Profile使用

    http://blog.csdn.net/he90227/article/details/52981747 摘要: spring Boot使用@Profile注解可以实现不同环境下配置参数的切换,任何 ...

  4. 【java】Map、Set、List不同数据结构的各种不同循环迭代的效率对比,使用场景

    Map.Set.List不同数据结构的各种不同循环迭代的效率对比,使用场景 引申一个地址:Map迭代的使用keySet和entitySet的效率

  5. 【Java Web开发学习】Spring环境profile

    [Java Web开发学习]Spring 环境profile 转载:http://www.cnblogs.com/yangchongxing/p/8890702.html 开发.测试.生产环境往往是不 ...

  6. Spring Boot Dubbo 应用启停源码分析

    作者:张乎兴 来源:Dubbo官方博客 背景介绍 Dubbo Spring Boot 工程致力于简化 Dubbo | grep tid | grep -v "daemon" tid ...

  7. ThreadLocal的理解与应用场景分析

    对于Java ThreadLocal的理解与应用场景分析 一.对ThreadLocal理解 ThreadLocal提供一个方便的方式,可以根据不同的线程存放一些不同的特征属性,可以方便的在线程中进行存 ...

  8. TYPESDK手游聚合SDK服务端设计思路与架构之一:应用场景分析

    TYPESDK 服务端设计思路与架构之一:应用场景分析 作为一个渠道SDK统一接入框架,TYPESDK从一开始,所面对的需求场景就是多款游戏,通过一个统一的SDK服务端,能够同时接入几十个甚至几百个各 ...

  9. Oracle dbms_lock.sleep()存储过程使用技巧-场景-分析-实例

    <Oracle dbms_lock.sleep()存储过程使用技巧>-场景-分析-实例 摘要:今天是2014年3月10日,北京,雾霾,下午组织相关部门开会.会议的结尾一名开发工程师找到了我 ...

随机推荐

  1. PHP操作Memcached的方法汇总

    memcached非关系型数据库安装.php中的memcache的扩展安装.以及php中的memcached的扩展安装可以参考: http://www.cnblogs.com/phpstudy2015 ...

  2. https原理及实践

    转载请注明出处 安全知识 网络安全问题 数据机密性 在网络传输数据信息时,对数据的加密是至关重要的,否则所有传输的数据都是可以随时被第三方看到,完全没有机密性可言. 数据机密性解决问题思路 利用算法 ...

  3. MySQL学习记录(不断更新)

    MySQL设置数据集为UTF8仍无法输入中文的解决办法: 我们的机器默认为gbk,因此可在进入数据库之前,使用以下这条语句将默认编码改为gbk,注意没有单引号,也不要用分号. mysql -uroot ...

  4. Windows Server 2016-FSMO操作主机角色介绍

    FSMO五个操作主机角色 1.林范围操作主机角色(两种): 架构主机角色:Schema Master 域命名主机角色:Domain Naming Master 2.域范围操作主机角色(三种): 域范围 ...

  5. 利用UICollectionView实现列表和宫格视图的切换

    很多时候我们需要列表和宫格视图的来回切换,就像苹果的天气应用一样,我之前见过一个用tableview和collectionview来实现这种效果的,我本人不太喜欢这个,那么有没有更好的方法呢?答案是: ...

  6. GO开发:接口

    接口 接口定义 Interface类型可以定义一组方法,但是这些不需要实现.并且interface不能包含任何变量. type example interface{ Method1(参数列表) 返回值 ...

  7. MathJax使用指南

    MathJax使用指南 SublimePrettyJson Github CSDN-Markdown语法集锦 LaTex 简明教程 在Markdown中输入数学公式(MathJax) MathJax ...

  8. wordpress配置固定链接nginx访问404问题解决方法

    WordPress支持使用固定链接,但是在ngnix环境下,访问页面后出现404, 其实官方是有文档说明的,需要单独写配置, 我这边配置的示例代码如下: server { listen       8 ...

  9. Linux 自定义命令

    在某个用户的家目录下 的 .bashrc 文件,写入如下内容: # .bashrc # Source global definitions if [ -f /etc/bashrc ]; then . ...

  10. python学习:函数传参数

    #!/usr/bin/python   import sys   def isNum(s):     for i in s:         if i in '0123456789':         ...