在spring boot官方文档中介绍了不少feature,我觉得有必要整理一下,还是挺有意思的。
文档中根据功能作出了以下区分:
- Core Feature: SpringApplication(Spring应用)| Externalized Configuration(外部配置)| Profiles(轮廓)| Logging(日志)
- Web Applications: MVC(不解释)| Embedded Containers(内嵌的容器)
- Working with data:SQL | NO-SQL
- Messaging: JMS(Java消息服务)
- Testing: Boot Applications | Utils (测试相关)
- Extending: Auto-configuration | @Conditions (拓展)
以上的feature用中文翻译起来很不容易理解,这些专业术语用英文表示更让人觉得熟悉。现在就针对某个feature单独去理解。
SpringApplication
这个特性可以说是spring boot的创新。在以往的web程序开发过程中,我们通常将自己的程序部署在tomcat或者weblogic类似的中间件上的,但使用spring boot不需要依耐这样的中间件。使用spring boot启动你的应用就像启动一个简单的程序一样,类似我们刚接触Java写的一个个的main函数一样。它只需要这样的代码就能启动一个web应用了:
正常启动肯定是没什么可讲的,问题是出了问题就很难受了。没关系,spring boot同样为开发者提供了很好的解决方案。spring boot提供FailureAnalyzers
帮助你修复问题。比方说,假如你在8080端口上启动web应用,然而这个端口被占用了,这时候控制台会报出这样的错误信息:
通过控制台打印出的错误信息,很容易知道问题出哪里了(英文水平不要太low)。当然这是使用默认的FailureAnalyzers
,spring boot 也提供自己定义的FailureAnalyzers
。在META-INF/spring.factories
这个文件中有这样的定义:
发现了这个PortInUseFailureAnalyzer
类吗?这个就是处理端口绑定失败的Analyzer。我们如果要自己定义一个这样的Analyzer很简单。创建一个类,继承AbstractFailureAnalyzer
,其中的泛型可以是任何异常。重写其analyze
方法,根据传入的参数进行处理,如果没办法处理那就返回一个null
,这时候将由下一个Analyzer去处理。如果可以处理,直接返回一个FailureAnalysis
对象即可。这个对象和Execption
很类似,无非就是一些错误信息罢了。这个是我定义的一个Analyzer:
定义这个类还没结束,还要创建一个META-INF/spring.factories
文件,内容如下:
除了这种方式诊断问题之外,还可以这样去发现问题。可以设置日志的级别:
假如你使用的是Java命令行的方式去启动你的app可以在命令后加这样的参数java -jar myproject-0.0.1-SNAPSHOT.jar --debug
,以debug的方式去启动。(我相信这种方式会让你的控制台爆炸,满屏都是日志,2333333。)
启动失败的问题分析我觉得不算特别有创新的feature,毕竟一般情况下通过报错也能找到问题出哪里了。
这个feature我觉得算是一个比较有意思的,虽然我觉得没什么屌用,只能算个彩蛋吧23333.
在我们点击run
的时候控制台会打印一个ASCII的字符画。开始以为这个是spring boot自带的,其实这个也可以自定义的。
在类路径下创建一个banner.txt文件,内容如下:
这样你的app在启动的时候就会打印这样的字符画了。个人觉得除了装b没有任何卵用。自己去定义这些字符画的生成程序也是可以的,org.springframework.boot.Banner
这个接口就是定义怎么去实现banner的打印的,具体怎么处理可以看看它的实现类。闲的没事可以去折腾这些玩意儿!当然不想看到这些东西也是可以的。在yml文件中这样配置一下就完事儿了:
同样的配置写成application.properties
也是OK的。
然鹅,硬编码也是可以的:
接下来的这个feature就比较实用了。我们用的是spring boot当然少不了核心的spring的特性呀,毕竟都姓spring嘛2333!
我们有时候需要在spring容器启动的时候搞一些事情,spring framework也提供了这样的一种机制去帮助我们完成。它定义了很多事件来抽象出这些操作,比如说ContextRefreshedEvent
这个事件就是当容器初始化或者被刷新了会触发。
我们注册一个bean可以通过@Bean
去完成,bean的注册需要依赖容器被创建,但是创建之前的一些操作我们没办法通过@Bean
来完成。spring boot中可以这样去设置SpringApplication.addListeners(…)
或者SpringApplicationBuilder.listeners(…)
去添加你关心的事件.当然这种方式是使用硬编码完成的,不够敞亮不够spring。可以在META-INF/spring.factories
文件中去指定。这是默认配置:
同样,自己去按照这样的写法去整一个自己定义的listener也是ok的,这很spring!文档中给了一段话:我们通常很少去用这个application event,但是我们知道他们存在是很有必要的。spring boot 通过他们完成很多任务。其实在做技术的过程中,也是这个道理,很多时候有些东西我们不常用,但是我们必须知道有这么个东西,说不定在什么时候就派上用场了。
这个feature我觉得没太多用处,毕竟我目前接触到spring boot不是很深入。spring boot启动入口是通过main
函数,其中有String[] args
作为参数传进来。spring boot提供ApplicationArguments
接口让我们直接获取传入的参数。
个人觉得使用这种方式很low,将参数直接写到配置文件中去,让app启动时候去读配置不完了?
如果你需要在SpringApplication启动前去做点别的事情,spring boot同样能够实现。
实现ApplicationRunner
接口同样也能达到效果。这个接口中的run
方法参数就是上面提到的ApplicationArguments
用来获取启动参数的。区别就在于一个只能获取String
数组类型的参数,一个能获取ApplicationArguments
类型的参数。
至此,关于Core Features: SpringApplication 的内容都梳理完了。下一个feature要讲的是Core Features: External Configuration。
Externalized Configuration
说实话,这个词中文翻译真的很难表达它想传达出的意思。作为名词的直译就是外部配置,作为动词翻译过来就是外部化配置。真的让人摸不到头脑。
仔细去读读内容,其实也就是一个关键词:配置。通过配置,可以让你的应用在不同环境中跑同一套代码。可以使用properties文件、YAML文件、environment变量、及命令行参数去使你的参数生效。配置参数可以通过使用@Value
注解直接注入到你的bean中。spring boot中的配置属性是遵循一个优先级的:
- 全局配置(当devtools生效的时候 ~/.spring-boot-devtools.properties文件作为全局配置文件)。
@TestPropertySource
注解配置在你的测试用例中。@SpringBootTest#properties
注解属性值被设置在你的测试用例中。- 命令行参数。
- environment variable(启动时候可以设置的参数,类似于program arguments)或者系统参数。
ServletConfig
初始化参数。ServletContext
初始化参数。java:comp/env
JNDI参数。- Java System properties(System.getProperties()).
- OS environment variables.
- A
RandomValuePropertySource
that only has properties in random.*.(啥啥啥,说啥呢) - jar包外的
application-{profile}.properties
配置文件或者YAML文件。 - jar包内的…(同上)。
- jar包外的
application.properties
文件或者YAML文件。 - jar包内的…(同上)。
- 在
@Configuration
注解过的类上的@PropertySource
属性(貌似读不通)。 - 默认属性。
一个栗子:123456789public class MyBean {"${name}")(private String name;// ...}
application.properties
中有name这个属性就会被自动赋值给name字段。java -jar app.jar --name="Spring"
这种方式name就是从命令行中去读取。
我们的配置文件除了application.properties
还有这种形式的:application-{profile}.properties
这个profile决定你代码运行的环境。可以是dev、prod等等。具体去加载哪个配置文件取决于spring.profiles.active
这个属性到底是什么。与之对应即可。如果有多个application-{profile}.properties
文件出现,最后出现的生效。
spring推荐使用YMAL作为配置文件。它是JSON的超集。spring framework提供了2个方便的类加载YMAL文件:YamlPropertiesFactoryBean
和YamlMapFactoryBean
。前者加载成一个Properties
,后者加载成一个Map
。
|
|
看上去有种很酸爽的感觉。
在一个YMAL文件中也可以指定不同的profile的。
server.address
属性在不同的profile中是不同的。development
被激活了,就使用127.0.0.1
.其他类似。都没激活就使用默认的192.168.1.100
.
然而这种方式有缺点,不能通过@PropertySource
注解直接注入到bean属性中。
spring针对@Value("${property}")
这种方式去注入属性提供一个替换。那就是使用@ConfigurationProperties("foo")
来放到你要注入的类中。字段名对应即可,即使有那种继承结构也没关系。YMAL本身对这种继承结构支持的很好。
关于Externalized Configuration的梳理也差不多了。各种炫酷屌炸天。
剩下的在以后几篇文章中继续整理。越来越有趣了。