平时项目中经常使用Spring Boot,却没有时间整理成一个比较系统的知识,这里罗列并总结下Spring Boot相关的知识点。知其然,更知其所以然,写之前,突然想了解一下Spring和Spring Boot的历史,查找资料,顺便记录在此了解一下吧。
2002年,美国小伙子Rod Johnson(还是一位音乐学博士)编写了一本书《Expert One-on-One J2EE》,直指当时J2EE和EJB开发的臃肿和缺陷,并提供了解决依赖注入的更简单的解决方案。书发布之后,开发者 Juergen Hoeller 和 Yann Caroff 就说服了Rod Johnson 创建一个基于基础结构代码的开源项目。Yann 为新框架创造了“Spring”的名字,意味着spring是传统J2EE的新开始。
2004年,Spring 1.0发布。
随着使用 Spring 进行开发的个人和企业越来越多,Spring 也慢慢从一个单一简洁的小框架变成一个大而全的开源软件,Spring 的边界不断的进行扩充,到了后来 Spring 几乎可以做任何事情了,市面上主流的开源软件、中间件都有 Spring 对应组件支持,人们在享用 Spring 的这种便利之后,也遇到了一些问题。Spring 每集成一个开源软件,就需要增加一些基础配置,慢慢的随着人们开发的项目越来越庞大,往往需要集成很多开源软件,因此后期使用 Spring 开发大型项目需要引入很多配置文件,太多的配置非常难以理解,并容易配置出错,到了后来人们甚至称 Spring 为配置地狱。Spring 似乎也意识到了这些问题,急需有这么一套软件可以解决这些问题,这个时候微服务的概念也慢慢兴起,快速开发微小独立的应用变得更为急迫,Spring 刚好处在这么一个交叉点上,于 2013 年初开始的 Spring Boot 项目的研发,2014年4月,Spring Boot 1.0.0 发布。
2014年,Spring Boot 1.0发布。
2004~2014,整整10年。
Spring Boot场景启动器(starter)
Spring Boot将所有功能场景都抽取成一个个starter,我们一般web开发,只需引入spring-boot-starter-web,该starter就导入了web开发相关的jar包。
注意到,上面的spring-boot-starter-web并没有写版本号, 因为Spring Boot中maven的pom文件默认继承了spring-boot-starter-parent。
而spring-boot-starter-parent继承了spring-boot-dependencies,其中维护了jar包的版本,包括了spring-boot-starter-web的版本。
jar包版本配置
Spring Boot自动化配置
通过上面的步骤,Spring Boot已经能够导入开发所需的jar包,那Spring Boot又是怎么为这些jar包配置默认值的呢? 答案就在Spring Boot的启动类上的注解@SpringBootApplication中。
@SpringBootApplication主要由三个注解构成:
@SpringBootConfiguration
、@EnableAutoConfiguration
、@ComponentScan
@SpringBootConfiguration
底层其实是@Configuration
,说明是一个配置类。@ComponentScan
则是配置了当前类(启动类)下的所有包到扫描到Spring容器,同时使用FilterType.CUSTOM
排除了一些需要类。@EnableAutoConfiguration
底层是由两个注解组成,@AutoConfigurationPackage
、@Import(AutoConfigurationImportSelector.class)
@AutoConfigurationPackage
其底层,还是一个@Import(AutoConfigurationPackages.Registrar.class)
,其将会把启动类的包下的组件都扫描到Spring容器中。@Import(AutoConfigurationImportSelector.class)
自动配置的奥妙就在这里啦,这个类导入了很多自动配置类,debug一下可以发现,其读取的是classpath下的META-INF/spring.factories下的自动配置类
自动配置类如下:
取一个出来看下,可以发现,该类是@Configuration配置类,所以默认的配置都在这里了,但是这些配置类并不是都生效,因为使用了@ConditionalOnClass,需满足一定的条件才会生效配置。
Spring Boot自动化配置总结
Spring Boot通过maven中的starter导入了所需场景下的jar包,并通过主启动类上的@SpringBootApplication中的@EnableAutoConfiguration读取了类路径下的META-INF/spring.factories下EnableAutoConfiguration的配置类,但是这些配置类使用了@ConditionalOnClass,需满足一定的条件才会激活配置,这些配置类写入了默认的配置。
自定义Spring Boot场景启动器
既然知道了starter中jar包的导入和@EnableAutoConfiguration工作原理,那么,我们可以自定义一个自己的场景启动器。
夜深了,晚上0点30分了,明天早点起床再继续吧。
继续,首先我们新建一个普通的工程,取名为starter,导入我们需要的jar,然后,为了能自定义配置我们的jar,那么我们总需要有地方给我们写@Configuration配置吧。Ok,新建一个自动化配置工程,在starter工程pom文件中引入。
我们这个工程呢,是一个服务器,可以配置一个端口,默认是80 。如下,新建一个@Configuration配置类,绑定配置文件的myserver.port属性。
再写一个服务类,绑定(打印)这个端口号。
既然组件都有了,那把这些组件组合起来,放到spring容器中管理吧,写一个配置类。
大功告成,将autoconfigurationdemo使用maven install到仓库,再starter中就可以引入了。再新建一个测试工程,可以导入starter进行测试,如下。
不配置端口时,默认的是80端口,如下:
配置了端口9090,如图,则绑定到9090端口。
至此,springboot自动化配置原理大致如上。