赞
踩
Spring Boot源代码有两种方式:直接获取整个项目源代码,创建Maven项目后间接加载源代码。我推荐使用第二种方式。
Spring Boot默认采用main方法启动,入口方法为SpringApplication类的run方法。
常见的代码阅读工具,比如Intellij IDEA、Spring Tool Suite、Eclipse、MyEclipse等。
Spring Boot本身并不提供Spring的核心功能,而是作为Spring的脚手架框架,以达到快速构建项目、预置三方配置、开箱即用的目的。
约定优于配置(Convention Over Configuration),又称为按约定编程,是一种软件设计范式,旨在减少软件开发人员需要做决定的数量,执行起来简单而又不失灵活。
Starter作为SpringBoot的核心功能之一,基于自动配置代码提供了自动配置模块及依赖,让软件集成变得简单、易用。
图1-4中为了更清晰地表达Spring Boot各项目之间的关系,我们基于依赖的传递性,省略了部分依赖关系。比如,Spring Boot Starters不仅依赖了Spring Boot Autoconfigure项目,还依赖了SpringBoot和Spring,而Spring Boot Autoconfigure项目又依赖了Spring Boot,Spring Boot又依赖了Spring相关项目。因此在图中就省略了Spring Boot Starters和底层依赖的关联。
从图1-4中可以看到Spring Boot几乎完全基于Spring,同时提供了Spring Boot和SpringBoot Autoconfigure两个核心的模块,而其他相关功能又都是基于这两个核心模块展开的。
Spring Boot最核心的功能就是自动配置,功能的实现都是基于“约定优于配置”的原则。Spring Boot是如何约定,又是如何实现自动配置功能的呢?
使用Spring Boot时只需引入对应的Starters,Spring Boot启动时便会自动加载相关依赖,配置相应的初始化参数,这便是Spring Boot的自动配置功能。先从整体上看一下Spring Boot实现该运作机制涉及的核心部分,如图2-1所示。
Spring Boot通过@EnableAutoConfiguration注解开启自动配置,加载spring.factories中注册的各种AutoConfiguration类,当某个AutoConfiguration类满足其注解@Conditional指定的生效条件(Starters提供的依赖、配置或Spring容器中是否存在某个Bean等)时,实例化该AutoConfiguration类中定义的Bean(组件等),并注入Spring容器,就可以完成依赖框架的自动配置。
@EnableAutoConfiguration是开启自动配置的注解,是由组合注解@SpringBootApplication引入的。
Spring Boot项目创建完成会默认生成一个*Application的入口类,入口类的命名规则都是artifactId+Application。通过该类的main方法即可启动Spring Boot项目,代码如下。
@SpringBootApplication部分源代码如下:
通过以上源代码发现,Spring Boot中大量使用了@AliasFor注解,该注解用于桥接到其他注解,该注解的属性中指定了所桥接的注解类。如果点进去查看,会发现@SpringBootApplication定义的属性在其他注解中已经定义过。之所以使用@AliasFor注解并重新在@SpringBootApplication中定义,更多是为了减少用户使用多注解带来的麻烦。
@SpringBootConfiguration并在其内组合了@Configuration。@EnableAutoConfiguration注解组合了@AutoConfigurationPackage。
在未使用Spring Boot的情况下,Bean的生命周期由Spring来管理,然而Spring无法自动配置@Configuration注解的类。Spring Boot的核心功能之一就是根据约定自动管理该注解标注的类。用来实现该功能的组件之一便是@EnableAutoConfiguration注解。
@EnableAutoConfiguration的主要功能是启动Spring应用程序上下文时进行自动配置,它会尝试猜测并配置项目可能需要的Bean。自动配置通常是基于项目classpath中引入的类和已定义的Bean来实现的。在此过程中,被自动配置的组件来自项目自身和项目依赖的jar包中。
@EnableAutoConfiguration的主要功能是启动Spring应用程序上下文时进行自动配置,它会尝试猜测并配置项目可能需要的Bean。自动配置通常是基于项目classpath中引入的类和已定义的Bean来实现的。在此过程中,被自动配置的组件来自项目自身和项目依赖的jar包中。
@EnableAutoConfiguration注解的源码:
需要注意的是,被@EnableAutoConfiguration注解的类所在package还具有特定的意义,通常会被作为扫描注解@Entity的根路径。这也是在使用@SpringBootApplication注解时需要将被注解的类放在顶级package下的原因。而对于入口类和其main方法来说,并不依赖@SpringBootApplication注解或@EnableAutoConfiguration注解,也就是说该注解可以使用在其他类上,而非入口类上。
@EnableAutoConfiguration的关键功能是通过@Import注解导入的ImportSelector来完成的。从源代码得知@Import(AutoConfigurationImportSelector.class)是@EnableAutoConfiguration注解的组成部分,也是自动配置功能的核心实现者。@Import(AutoConfigurationImportSelector.class)又可以分为两部分:@Import和对应的ImportSelector。
@Import注解位于spring-context项目内,主要提供导入配置类的功能。
@Import的作用和xml配置中<import/>标签的作用一样,可通过@Import引入@Configuration注解的类,也可以导入实现了ImportSelector或ImportBeanDefinitionRegistrar的类,还可以通过@Import导入普通的POJO(将其注册成Spring Bean,导入POJO需要Spring 4.2以上版本)。
@Import的许多功能都需要借助接口ImportSelector来实现,ImportSelector决定可引入哪些@Configuration。ImportSelector接口源码如下。
ImportSelector接口提供了一个参数为AnnotationMetadata的方法,返回的结果为一个字符串数组。其中参数AnnotationMetadata内包含了被@Import注解的类的注解信息。在selectImports方法内可根据具体实现决定返回哪些配置类的全限定名,将结果以字符串数组的形式返回。
ImportSelector接口只提供了一个参数为AnnotationMetadata的方法,返回的结果为一个字符串数组。参数AnnotationMetadata内包含了被@Import注解的类的注解信息。在selectImports方法内可根据具体实现决定返回哪些配置类的全限定名,将结果以字符串数组的形式返回。
在AutoConfigurationImportSelector的源代码中就实现了这4个接口:
AutoConfigurationImportSelector实现了ImportSelector接口的子接口DeferredImportSelector。DeferredImportSelector接口与ImportSelector的区别是,前者会在所有的@Configuration类加载完成之后再加载返回的配置类,而ImportSelector是在加载完@Configuration类之前先去加载返回的配置类。DeferredImportSelector的加载顺序可以通过@Order注解或实现Ordered接口来指定。同时,DeferredImportSelector提供了新的方法getImportGroup()来跨DeferredImportSelector实现自定义Configuration的加载顺序。
从整体上了解AutoConfigurationImportSelector的核心功能及流程,然后再对照代码看具体的功能实现。图2-3中省略了外部通过@Import注解调用该类的部分。
当AutoConfigurationImportSelector被@Import注解引入之后,它的selectImports方法会被调用并执行其实现的自动装配逻辑。
检查自动配置是否开启,如果开启自动配置功能,就继续执行后续操作;如果未开启,就返回空数组。代码如下。
EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY的配置,该常量的值为spring.boot.enableautoconfiguration。如果获取不到该属性的配置,isEnabled默认为true,也就是默认会使用自动配置。如果当前类为其他类,直接返回true。
在application.properties或application.yml中针对此参数进行配置。以application.properties配置关闭自动配置为例,代码如下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。