Spring Boot————简介与Spring时代的承接

引言

最近,公司正在开发一个景区系统的项目,涉及到Spring Boot框架的使用,在此记录下Spring Boot框架应该知道的基础知识。

一、产生

SpringBoot是顺应现在微服务(MicroServices)理念而产生的一个微框架(同类还有Dropwizard),用来构建基于Spring框架的标准化的独立部署应用程序。

二、SpringBoot快速开始:

我们使用Maven构建项目,所以新建一个maven项目, pom.xml中添加如下两个关键因素:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>
...
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

使用spring-boot-starter-parent作为当前项目的parent可以享受到spring boot应用相关的一系列依赖(dependency), 插件(plugins)等装备, 而添加spring-boot-starter-web这个依赖,则纯粹是我们希望构建一个独立运行的web应用而已(注意, 没有version元素定义,因为spring-boot-starter-parent已经提供了相应的dependencyManagement)。有了以上配置,我们就可以按照SpringMVC的套路添加相应的Controller实现就可以了。

要让Spring Boot可以独立运行和部署,我们需要一个Main方法入口。

三、Spring Boot如何工作

3.1 Spring 特性回顾

3.1.1 XML配置与JavaConfig的选择问题

SpringBoot倡导基于JavaConfig的形式来“装配”应用, 但有些层面,我们还是希望根据公司的生态圈和基础设施现状,对其进行一些定制,以便更好的融入并享受一系列生态,而大部分要集成外部已有系统的时候, 通过xml集中明确化配置我认为是比较合适的做法。

总之, 这两种方式不应该是东风压倒西风,而应该根据情况来选择。 从我的角度来讲,我希望在SpringBoot里,除了Main入口类和autoscan相关的地方使用JavaConfig, 其它最好以xml配置。

3.1.2 @Configuration注解

@Configuration这个注解就是JavaConfig的典型代表。标注了这个注解的Java类定义,会以Java代码的形式(对应于xml定义的形式)提供一系列的bean定义和实例。 结合AnnotationConfigApplicationContext自动扫描的功能,就可以构建一个基于Spring容器的Java应用。

一系列标注了@Configuration的Java类的集合,对应于“昨日”的一系列xml配置文件。

3.1.3 @ComponentScan注解

@ComponentScan对应xml时代的<context:component-scan>。用来扫描classpath下标注了相应注解的Bean定义,然后加载到Spring容器中。

一般配合@Configuration注解来使用,你可以将@Configuraiton做的事情是纯手工定义bean然后添加到Spring容器, 而@ComponentScan则是自动收集bean定义并添加到Spring容器。

3.1.4 @Import注解

Spring容器的配置可以分散在多个物理存在的配置类或者配置文件中。

@Import允许将其它JavaConfig形式的配置类引入到当前的@Configuration标注的配置类当中, 对应于原来xml时代的<import/>, 甚至于也可以通过@ImportResource将xml形式定义的配置也引入当前JavaConfig形式的配置类当中。

3.1.5 @PropertySource注解

配合@Configuration使用, 用来加载.properties内容到Environment,比如:@PropertySource("classpath:/application.properties"),并需要容器中配置一个PropertySourcesPlaceholderConfigurer。

@PropertySource和@PropertySources的区别在于, 后者属于前者的Aggregation类型, 在有多个.properties资源需要引入的情况下,如果能够使用Java8的repeatable annotation特性,则只需要声明多个@PropertySource就行了, 否则,作为fallback方案,使用@PropertySources然后再其中引用多个@PropertySource好了。

3.1.6 Environment和Profile

这两个概念应该是Spring3时代引入的, Environment用来统一表达当前应用程序运行环境的概念,会以Properties的形式提供一系列该环境下的上下文信息,而且允许当前应用程序获取activeProfile是哪个。
说实话,Environment的设计,我觉得到提供上下文信息这一关键职能就可以了, 而Profile的设计,则有些太过于Monolithic时代的做事风格。 Profile一般用来提供某些灵活性, 但这种灵活性是内部化的, 这意味着, 你的软件实体需要知道外面可能提供多少种profiles, 然后在不同的profile下,我的软件实体需要做什么样的调整。 而实际上, 软件实体从研发到交付和使用, 最好是在整条流水线上设计和生产都是一致, 只有“销售”之前,才根据目标环境或者目标客户调整“包装”和配置, 然后“发货”, 用户拿到手的产品(当然包括我们搞的软件产品)应该是开箱即用的, 这个产品既不会存在我不需要的功能,也不应该每次使用的时候先自己“很智能”的扫描一下上下文环境然后决定使用哪一个Profile。尤其是在微服务时代,随着你服务数量的增长, 服务数量 * Environment数量 * 所谓的Profile数量更是指数级增长 3, 如果应用开发的时候还要考虑这么多,那出问题的几率就更大了。
所以, 在Microservices时代,我们更建议外部化你的软件产品差异化配置管理, 尽量减少Profile的滥用甚至不用(这就减少一个纬度的管理)。

3.2 对@EnableAutoConfiguration的理解

在本文之前提到的所有Annotation都属于SpringFramework提供的, 现在要说的这个Annotation,即@EnableAutoConfiguration, 则属于SpringBoot。
@EnableAutoConfiguration的定义信息如下:

@Target(value=TYPE)
@Retention(value=RUNTIME)
@Documented
@Inherited
@Import(value={org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector.class,org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar.class})
public @interface EnableAutoConfiguration

标注了这个Annotation的配置类将触发一系列动作, 也是SpringBoot“黑魔法”的核心, 魔法大体上是这样发生的: SpringBoot一旦发现@EnableAutoConfiguration, 那么就使用Spring框架提供的SpringFactoriesLoader这个特性去扫描当前应用classpath下所有META-INF/spring.factories元信息配置, 然后根据当前使用场景需要, 加载符合当前场景需要的配置类型并供当前或者后继流程使用, 对于@EnableAutoConfiguration的场景,就是提取以org.springframework.boot.autoconfigure.EnableAutoConfiguration作为key标志的一系列Java配置类,然后将这些Java配置类中的bean定义加载或者说灌入Spring容器中。
当然, EnableAutoConfiguration通过SpringFactoriesLoader筛选并加载进来的这些Java配置类里面,我们其实还可以进一步对要加载到容器的bean定义进行筛选, 这就会用Spring3系列引入的@Conditional“军团”, 通过像@ConditionalOnClass, @ConditionalOnMissingBean等具体的类型和条件来进一步决定加载还是不加载哪些bean定义。

3.3 Enter Main

有了上面的这些“前戏”, 下面我们正式进入正题了...
每一个SpringBoot应用都有一个入口类,在其中定义main方法, 然后使用SpringApplication这个类来加载指定配置并运行SpringBoot应用程序, 在很多SpringBoot的介绍中,都会使用当前入口类既作为配置(标注@Configuration)又作为入口类, 比如我们的HellSpringBoot:

@SpringBootApplication
public class HelloSpringBoot {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(HelloSpringBoot.class, args);
    }
}

@SpringBootApplication等效于@Configuraiton + @EnableAutoConfiguration + @ComponentScan, 所以, 当我们将HelloSpringBoot.class作为JavaConfig配置类传入SpringApplication.run方法之后, SpringApplication.run方法就知道从哪里加载并扫描必要的bean定义了。
现在,剩下的就是要搞清楚SpringApplication.run里面发生了什么。

鸣谢

Spring Boot Rock’n’Roll

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页