springboot启动流程

springboot 启动原理
参考文档:https://mp.weixin.qq.com/s/1yHtaoSqqIJItIXByvV5QA

@SpringBootApplication注解与@EnableAutoConfiguration与AutoConfigurationImportSelector.class 与 SpringFactoriesLoader#

@SpringBootApplication = @Configuration+ @EnableAutoConfiguration+ @ComponentScan

@Configuration#

JavaConfig形式的Spring Ioc容器的配置类,等同于xml方式的

@ComponentScan:#

自动扫描并加载符合条件的组件(比如@Component和@Repository等)或者bean定义,最终将这些bean定义加载到IoC容器中。

@EnableAutoConfiguration#

借助@Import的支持,收集和注册特定场景相关的bean定义。
@AutoConfigurationPackage + @Import(AutoConfigurationImportSelector.class)

AutoConfigurationPackage将 添加该注解的类所在的package 作为 自动配置package 进行管理。

@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持。实现智能的自动配置。

SpringFactoriesLoader:
SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。
配合@EnableAutoConfiguration使用的话,它更多是提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类。

so:
@EnableAutoConfiguration自动配置的魔法骑士就变成了:从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

Springboot启动执行详细流程#

  1. SpringApplication初始化
    A.根据classpath里面是否存在某个特征类(org.springframework.web.context.ConfigurableWebApplicationContext)来决定是否应该创建一个为Web应用使用的ApplicationContext类型。
    B.使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationContextInitializer。
    C.使用SpringFactoriesLoader在应用的classpath中查找并加载所有可用的ApplicationListener。
    D.推断并设置main方法的定义类。

  2. SpringApplication run()
    A.加载所有SpringApplicationRunListener。调用它们的started()方法
    SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(bootstrapContext, this.mainApplicationClass);
    B. 创建并配置当前Spring Boot应用将要使用的Environment(包括配置要使用的PropertySource以及Profile)。
    ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); configureIgnoreBeanInfo(environment);
    C.遍历调用所有SpringApplicationRunListener的environmentPrepared()的方法,告诉他们:“当前SpringBoot应用使用的Environment准备好了咯!”
    D. 如果SpringApplication的showBanner属性被设置为true,则打印banner
    E. 根据用户是否明确设置了applicationContextClass类型以及初始化阶段的推断结果,决定该为当前SpringBoot应用创建什么类型的ApplicationContext并创建完成
    context = createApplicationContext(); F. 将之前准备好的Environment设置给创建好的ApplicationContext使用, 将遍历调用ApplicationContextInitializer的initialize(applicationContext)方法来对已经创建好的ApplicationContext进行进一步的处理 context.setEnvironment(environment);
    postProcessApplicationContext(context); applyInitializers(context);
    G. 遍历调用所有SpringApplicationRunListener的contextPrepared()方法。
    listeners.contextPrepared(context); H. 注册特殊定义bean(springApplicationArguments、springBootBanner), 添加LazyInitializationBeanFactoryPostProcessor,创建并初始化BeanDefinitionLoader(主要做的工作就是注册bean) I. 遍历调用所有SpringApplicationRunListener的contextLoaded()方法。 listeners.contextLoaded(context);
    J. 调用ApplicationContext的refresh()方法,完成IoC容器可用的最后一道工序.
    applicationContext.refresh(); K.执行ApplicationRunners,CommandLineRunners callRunners(context, applicationArguments);
    L.遍历执行SpringApplicationRunListener的started()方法

Springboot启动简要流程#

  1. SpringApplication 初始化,收集所有ApplicationContextInitializer和ApplicationListener。
  2. SpringApplication run
    调用started事件
    创建并准备Environment(PropertySource、Profile)
    调用environmentPrepared事件
    创建ApplicationContext,遍历调用ApplicationContextInitializer的initialize方法
    调用contextPrepared 事件
    创建并配置BeanDefinitionLoader
    调用contextLoaded 事件
    applicationContext的refresh()方法, 完成ioc容器初始化
    调用started事件
    callRunners(ApplicationRunners,CommandLineRunners)
    调用running事件

总结#

Springboot的启动,主要创建了配置环境(environment)、事件监听(listeners)、应用上下文(applicationContext),并基于以上条件,在容器中开始实例化我们需要的Bean
自动装配核心:@EnableAutoConfiguration中的AutoConfigurationImportSelector中的SpringFactoriesLoader 提供一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类。并在后续加载到ioc容器。

pageHelper-springboot

springboot Mybatis 数据库分页获取 ,使用pageHelper插件

maven

1
2
3
4
5
6
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>

引用此依赖可能会与其它springboot依赖冲突,此时可手动去除其它依赖

1
2
3
4
compile ('com.github.pagehelper:pagehelper-spring-boot-starter:1.2.5') {
exclude group: 'org.springframework.boot', module: ''
exclude group: 'org.mybatis.spring.boot', module: ''
}

application.properties

1
2
3
4
5
#pagehelper分页插件配置
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql

调用

1
2
PageHelper.startPage(pageNum, pageSize);
mapper.loadAll();

springboot文档阅读 第三章 配置信息读取

稍微粘贴一下配置文件信息,但还是没有总结出最佳实践,todo待总结,不过想必是spring源码的配置方式吧。

判断环境是否是web环境

SpringApplication将尝试为你创建正确类型的ApplicationContext,默认情况下,根据你开发的是否为web应用决定使用AnnotationConfigApplicationContextAnnotationConfigEmbeddedWebApplicationContext

用于确定是否为web环境的算法相当简单(判断是否存在某些类),你可以使用setWebEnvironment(boolean webEnvironment)覆盖默认行为。

springboot文档阅读 第二章 继承parent与远程调试

继承 starter parent ?

继承的话:

如果你想配置项目,让其继承自spring-boot-starter-parent,只需将parent按如下设置:

1
2
3
4
5
6
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.BUILD-SNAPSHOT</version>
</parent>

:你应该只需在该依赖上指定Spring Boot版本,如果导入其他的starters,放心的省略版本号好了。

按照以上设置,你可以在自己的项目中通过覆盖属性来覆盖个别的依赖。例如,你可以将以下设置添加到pom.xml中来升级Spring Data到另一个发布版本。

1
2
3
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

查看spring-boot-dependencies pom获取支持的属性列表。

spring-boot-starter-parent选择了相当保守的Java兼容策略,如果你遵循我们的建议,使用最新的Java版本,可以添加一个java.version属性:

1
2
3
<properties>
<java.version>1.8</java.version>
</properties>

Spring Boot包含一个[Maven插件](../VIII. Build tool plugins/58. Spring Boot Maven plugin.md),它可以将项目打包成一个可执行jar。如果想使用它,你可以将该插件添加到<plugins>节点处:

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

:如果使用Spring Boot starter parent pom,你只需添加该插件而无需配置它,除非你想改变定义在partent中的设置。

springboot文档阅读 第一章

@RestController和@RequestMapping

Example类上使用的第一个注解是@RestController,这被称为构造型(stereotype)注解。它为阅读代码的人提供暗示(这是一个支持REST的控制器),对于Spring,该类扮演了一个特殊角色。在本示例中,我们的类是一个web @Controller,所以当web请求进来时,Spring会考虑是否使用它来处理。

@RequestMapping注解提供路由信息,它告诉Spring任何来自”/“路径的HTTP请求都应该被映射到home方法。@RestController注解告诉Spring以字符串的形式渲染结果,并直接返回给调用者。

@RestController@RequestMapping是Spring MVC中的注解(它们不是Spring Boot的特定部分),具体参考Spring文档的MVC章节

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×