现在大家都追赶新的技术潮流,我来逆行一下。

其实Spring Boot 隐藏了大量的细节,有大量的默认配置,其实通过xml配置的方式也可以达到和Spring Boot一样的效果。

Profile

在Spring Boot项目中我们通过application.properties中的设置来配置使用哪个配置文件application-dev.properties,application-prod.properties等等

spring.profiles.active=dev

Spring 3.0以后就包含了Profile功能,在xml中可以这么写,不过所有的bean需要显式的配置。需要弄清楚自己项目的依赖关系,在Spring中第三方包如何初始化。

<beans profile="dev,test"><bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:application-dev.properties" /></bean>
</beans><beans profile="prod"><bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"><property name="location" value="classpath:application-prod.properties" /></bean>
</beans>

在Spring Boot中大量的Jave Bean都包含了默认初始化的功能,只需要配置预先设置好的属性名称,但是在xml中需要显式的初始化Bean,并且可以在初始化的时候用Placeholder来配置。

Environment

在 Spring Boot 项目中application.propertiesapplication-xxx.properties 中的变量会自动放到 Environment中,并且可以通过@Value直接注入到变量中。

如果使用 ClassPathXmlApplicationContext 初始化项目,可以看到源代码里 Environment 是一个 StandardEnvironment 实例,仅仅包含系统变量和环境变量,为了把application-xxx.properties放到 Environment 当中我们需要扩展一下 ClassPathXmlApplicationContext,下面是CustomApplicationContextCustomEnvironment

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;public class CustomApplicationContext extends ClassPathXmlApplicationContext {public CustomApplicationContext(){super();}public CustomApplicationContext(String configLocation) {super(new String[]{configLocation}, true, null);}@Overridepublic ConfigurableEnvironment createEnvironment() {return new CustomEnvironment();}
}
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePropertySource;import java.io.IOException;public class CustomEnvironment extends StandardEnvironment {private static final String APPCONFIG_PATH_PATTERN = "classpath:application-%s.properties";@Overrideprotected void customizePropertySources(MutablePropertySources propertySources) {super.customizePropertySources(propertySources);try {propertySources.addLast(initResourcePropertySourceLocator());} catch (IOException e) {logger.warn("failed to initialize application config environment", e);}}private PropertySource<?> initResourcePropertySourceLocator() throws IOException {String profile = System.getProperty("spring.profiles.active", "dev");String configPath = String.format(APPCONFIG_PATH_PATTERN, profile);System.out.println("Using application config: " + configPath);Resource resource = new DefaultResourceLoader(this.getClass().getClassLoader()).getResource(configPath);PropertySource resourcePropertySource = new ResourcePropertySource(resource);return resourcePropertySource;}
}

日志配置

Spring Boot 默认使用的是logback,在logback-spring.xml 的配置文件中可以使用Spring Profile,而且还有一个默认的CONSOLE Appender

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<springProfile name="dev,test"><logger name="org.springframework" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</springProfile>
<springProfile name="prod"><logger name="org.springframework" level="INFO" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</springProfile>
</configuration>

在没有使用Spring Boot的情况下,不能在logback的config中使用Spring Profile,只能分拆成多个文件,然后根据环境变量读取不同的配置文件,需要添加依赖org.logback-extensions

<dependency><groupId>org.logback-extensions</groupId><artifactId>logback-ext-spring</artifactId><version>0.1.4</version>
</dependency>

logback-dev.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n}"/><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><logger name="org.springframework" level="DEBUG" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</configuration>

logback-prod.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration><property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n}"/><appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><logger name="org.springframework" level="INFO" additivity="false"><appender-ref ref="CONSOLE"/></logger>
</configuration>

下面的代码根据环境变量读取不同的配置文件

    private static final String LOGCONFIG_PATH_PATTERN = "classpath:logback-%s.xml";public static void main(String[] args) throws FileNotFoundException, JoranException {String profile = System.getProperty("spring.profiles.active", "dev");System.setProperty("file.encoding", "utf-8");// logback configString logConfigPath = String.format(LOGCONFIG_PATH_PATTERN, profile);System.out.println("Using logback config: " + logConfigPath);LogbackConfigurer.initLogging(logConfigPath);SLF4JBridgeHandler.removeHandlersForRootLogger();SLF4JBridgeHandler.install();ConfigurableApplicationContext context = new CustomApplicationContext("classpath:applicationContext.xml");}

测试

有Spring Boot 的时候TestCase写起来很方便,在类上添加两行注解即可,在src\test\resources下的application.properties中设置spring.profiles.active=test即可指定Profile为test

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestStockService {@AutowiredStockService stockService;@Beforepublic void setUp() {}@Afterpublic void tearDown() {}@Testpublic void testMissingBbTickerEN() {}
}

不使用Spring Boot的情况下,需要指定好几个配置。

@RunWith(SpringRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
@ActiveProfiles(profiles = "test")
@TestPropertySource("classpath:application-test.properties")
public class TestStockService {@AutowiredStockService stockService;@Beforepublic void setUp() {}@Afterpublic void tearDown() {}@Testpublic void testMissingBbTickerEN() {}
}

打包

Spring Boot 会把项目和所依赖的 Jar 包打包成一个大 Jar 包,直接运行这个 Jar 包就可以。这个功能是通过spring-boot-maven-plugin实现的。

<plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

不使用Spring Boot 之后,我们需要配置maven-jar-plugin,但是依赖包无法像Spring Boot一样打包成一个大的 Jar 包,需要我们指定classpath。

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.6</version><configuration><archive><manifest><mainClass>com.exmaple.demo.DemoApplication</mainClass><addClasspath>true</addClasspath><classpathPrefix>lib/</classpathPrefix></manifest></archive></configuration>
</plugin>

注意:

当用java -jar yourJarExe.jar来运行一个经过打包的应用程序的时候,你会发现如何设置-classpath参数应用程序都找不到相应的第三方类,报ClassNotFound错误。实际上这是由于当使用-jar参数运行的时候,java VM会屏蔽所有的外部classpath,而只以本身yourJarExe.jar的内部class作为类的寻找范围。所以需要在jar包mainfest中添加classpath。

依赖包

使用下面的maven配置帮你把所有的依赖包复制到targetlib目录下,方便我们部署或者是测试时复制依赖包。

<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><executions><execution><id>copy-dependencies</id><phase>prepare-package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>target/lib</outputDirectory><overWriteIfNewer>true</overWriteIfNewer><excludeGroupIds>junit,org.hamcrest,org.mockito,org.powermock,${project.groupId}</excludeGroupIds></configuration></execution></executions><configuration><verbose>true</verbose><detail>true</detail><outputDirectory>${project.build.directory}</outputDirectory></configuration>
</plugin>

运行

运行时通过指定命令行参数 -Dspring.profiles.active=prod 来切换profile

java -jar -Dspring.profiles.active=prod demo.jar

总结

Spring Boot很大程度上方便了我们的开发,但是隐藏了大量的细节,我们使用xml配置spring可以达到差不多同样的效果,但是在结构和配置上更加清晰。

如何把Spring Boot 项目变成一个XML配置的Spring项目相关推荐

  1. Spring Boot入门系列(六)Spring Boot如何使用Mybatis XML 配置版【附详细步骤】

    前面介绍了Spring Boot 中的整合Thymeleaf前端html框架,同时也介绍了Thymeleaf 的用法.不清楚的朋友可以看看之前的文章:https://www.cnblogs.com/z ...

  2. (转)Spring Boot(二十):使用 spring-boot-admin 对 Spring Boot 服务进行监控

    http://www.ityouknow.com/springboot/2018/02/11/spring-boot-admin.html 上一篇文章<Spring Boot(十九):使用 Sp ...

  3. [Spring Boot]Druid datasource整合及配置

    [Spring Boot]Druid datasource整合及配置 创建Spring Boot项目 这里使用默认配置创建一个空项目 demo-druid 用作演示,可跳过这一段: 只勾选基本的Spr ...

  4. springboot日志写入mysql_44. Spring Boot日志记录SLF4J【从零开始学Spring Boot】

    学院中有Spring Boot相关的课程!点击「阅读原文」进行查看! SpringSecurity5.0视频:http://t.cn/A6ZadMBe Sharding-JDBC分库分表实战: 在开发 ...

  5. 14. Spring Boot定时任务的使用【从零开始学Spring Boot】

    [视频 & 交流平台] à SpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008& ...

  6. Spring Boot 面试,一个问题就干趴下了!

    最近栈长面试了不少人,其中不乏说对 Spring Boot 非常熟悉的,然后当我问到一些 Spring Boot 核心功能和原理的时候,没人能说得上来,或者说不到点上,可以说一个问题就问趴下了! 这是 ...

  7. Spring Boot(5)---第一个Spring Boot应用程序

    Spring Boot入门:开发您的第一个Spring Boot应用程序 本节介绍如何开发一个简单的"Hello World!"Web应用程序,该应用程序重点介绍Spring Bo ...

  8. java application.xml_第4章 零XML配置的Spring Boot Application

    第4章 零XML配置的Spring Boot Application Spring Boot 提供了一种统一的方式来管理应用的配置,允许开发人员使用属性properties文件.YAML 文件.环境变 ...

  9. Spring Boot 面试,一个问题就干趴下了

    最近栈长面试了不少人,其中不乏说对 Spring Boot 非常熟悉的,然后当我问到一些 Spring Boot 核心功能和原理的时候,没人能说得上来,或者说不到点上,可以说一个问题就问趴下了! 这是 ...

最新文章

  1. ocp 042 第十一章:管理oracle网络配置
  2. 黑客攻防:从入门到入狱_每日新闻摘要:游戏服务黑客被判入狱27个月
  3. LeetCode 1450. 在既定时间做作业的学生人数
  4. linux实现防止恶意扫描 PortSentry
  5. Chelly的串串专题
  6. simulink教程(自动控制原理)
  7. js截取中英文字符串
  8. 服务器的上行带宽和下行带宽是什么意思
  9. 扑克牌排序(结构体)
  10. 代理IP是什么意思?浏览器代理和代理服务器是什么(小白必看,看了必会,不看血亏)
  11. zz我们都回不去了-南大校门被拆
  12. rqt_publisher包用法详解
  13. 流行和声(4)Major7和弦
  14. Maven打包Excel等资源文件损坏问题
  15. 使用U盘启动盘安装Imperva MX13.0
  16. 深入理解MyBatis(七)—MyBatis事务
  17. java hgetall_详解Java使用Pipeline对Redis批量读写(hmsethgetall)
  18. 如何给网站做SEO优化?
  19. 很抱歉,OneDrive服务器出现问题,请稍后重试。(错误代码:0x8004def5)
  20. 如何恢复录音删除的录音文件_电脑录音软件如何定时自动录音

热门文章

  1. coalesce函数_什么是SQL Server COALESCE()函数?
  2. Akka向设备组添加Actor注册《thirteen》译
  3. 适配器模式的极简概述
  4. Git合并特定commits 到另一个分支
  5. 我是小白一个,如何快速学会C++?
  6. CakePHP 3.7.6 发布,PHP 快速开发框架
  7. 使用LDAP查询快速提升域权限
  8. BlockChange丨谁在监管加密货币?各国数字货币政策情况概览
  9. Activity管理笔记
  10. Android数据存储(1):SharedPreferences