1、分析spring-boot-starter-parent

 <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.RELEASE</version>
</parent>
他的父项目
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.6.RELEASE</version>
<relativePath>../../spring-boot-dependencies</relativePath>
</parent>
他来真正管理Spring Boot应用里面的所有依赖版本;

按照Ctrl点击pom.xml中的spring-boot-starter-dependencies,跳转到了spring-boot-starter-dependencies的pom.xml,xml配置如下(只摘抄了部分重点配置):

从上面的spring-boot-starter-dependencies的pom.xml中可以发现,一部分坐标的版本、依赖管理、插件管理已经定义好,所以SpringBoot工程继承spring-boot-starter-parent后已经具备版本锁定等配置了。所以起步依赖的作用就是进行依赖的传递。以后我们导入依赖默认是不需要写版本;(没有在dependencies里面管理的依赖自然需要声明版本号)

2、分析spring-boot-starter-web启动器

  <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

spring-boot-starter-web:
        spring-boot-starter:spring-boot场景启动器;帮我们导入了web模块正常运行所依赖的组件;
        Spring Boot将所有的功能场景都抽取出来,做成一个个的starters(启动器),只需要在项目里面引入这些starter
       相关场景的所有依赖都会导入进来。要用什么功能就导入什么场景的启动器

3、主程序类,主入口类

/**
* @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class HellStartMain {
public static void main(String[] args) {
//spring启动起来
SpringApplication.run(HellStartMain.class);
}
}

1、@SpringBootApplication

Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot
就应该运行这个类的main方法来启动SpringBoot应用;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication

2、@SpringBootConfiguration

SpringBoot的配置类,标注这个类,表明SpringBoot是一个配置类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration{
@Configuration:配置类上面标注这个注解
配置类---配置文件;配置也是一个组件;@Component
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {

3、@EnableAutoConfiguration

 开启自动配置功能;以前需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
AutoConfigurationPackage:自动导入包
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage { Spring的底层注解@Import,给容器中导入一个组件;导入的组件由AutoConfigurationPackages.Registrar.class;
将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器;
@Import(AutoConfigurationImportSelector.class)给容器导入组件
public class AutoConfigurationImportSelector{
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}
}
}

EnableAutoConfigurationImportSelector:导入哪些组件的选择器;
将所有需要导入的组件以全类名的方式返回;这些组件就会被添加到容器中;
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);就是给容器中导入这个场景需要的所有组件,
并配置好这些组件;有了自动配置类,免去了我们手动编写配置注入功能组件等的工作;

​  SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);

Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,

自动配置类就生效,帮我们进行自动配置工作;以前我们需要自己配置的东西,自动配置类都帮我们;

其中,SpringFactoriesLoader.loadFactoryNames 方法的作用就是扫描所有jar包类路径下 META-INF/spring.factories文件中读取指定类对应的类名称列表,把扫描到的这些文件的内容包装成properties对象

从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中

spring.factories 文件中有关自动配置的配置信息如下:

J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfigure-2.0.6.RELEASE.jar;
												

spring boot原理分析的更多相关文章

  1. spring boot原理分析启动依赖中parent帮我们干了什么

    主要内容: 1:分析spring-boot-starter-parent 这个依赖 通过前面几篇文章的学习,我们感受到了spring boot的魅力.最明显的感觉就是pom.xml文件.代码少了很多. ...

  2. Spring事务原理分析-部分二

    Spring事务原理分析-部分二 说明:这是我在蚂蚁课堂学习了余老师Spring手写框架的课程的一些笔记,部分代码代码会用到余老师的课件代码.这不是广告,是我听了之后觉得很好. 课堂链接:Spring ...

  3. Spring事务原理分析-部分一

    Spring事务原理分析-部分一 什么事务 事务:逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败. 事务基本特性 ⑴ 原子性(Atomicity) 原子性是指事务包含的所有操作要 ...

  4. Spring lazy-init 原理分析

    普通的bean的初始化是在容器启动初始化阶段执行的,而被lazy-init修饰的bean 则是在从容器里第一次进行context.getBean(“”)时进行触发.Spring 启动的时候会把所有be ...

  5. Spring Mvc原理分析(一)

    Servlet生命周期了解 Servlet的生命(周期)是由容器(eg:Tomcat)管理的,换句话说,Servlet程序员不能用代码控制其生命. 加载和实例化:时机取决于web.xml的定义,如果有 ...

  6. Spring事务原理分析--手写Spring事务

    一.基本概念和原理 1.Spring事务 基于AOP环绕通知和异常通知的 2.Spring事务分为编程式事务.声明事务.编程事务包括注解方式和扫包方式(xml) Spring事务底层使用编程事务(自己 ...

  7. spring boot 原理解析一(spring boot 基础特征)

    spring boot 提供了完整的介绍 文档:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/html/documen ...

  8. Spring Boot原理

    Spring 钩子之BeanFactoryPostProcessor和BeanPostProcessor的源码学习 https://www.jianshu.com/p/a90a3e617ba6 spr ...

  9. Spring核心原理分析之MVC九大组件(1)

    本文节选自<Spring 5核心原理> 1 什么是Spring MVC Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架,本质上相当于 S ...

随机推荐

  1. Verilog之语句位置

    1.if语句.case语句必须放在always过程语句块中. 2.verilog的系统函数比如:\(display/\)monitor必须放在initial 过程语句块中.这点尚为理解为何,但必须这样 ...

  2. 【mysql】The server quit without updating PID file

      groupadd mysql useradd -r -g mysql mysql cd /usr/local/mysql chown -R mysql:mysql . scripts/mysql_ ...

  3. Python基础(五)——闭包与lambda的结合

    (1)变量的域 要了解闭包需要先了解变量的域,也就是变量在哪一段“上下文”是有效的(类似局部变量和全局变量的区别),举一个很简单的例子.(例子不重要,就是涉及闭包就要时刻关注这个域) def test ...

  4. 初学Python02

    数据类型和变量: 1.整数  整数在Python中直接输入就好,没有特殊要求(正负整数皆可).由于计算机是二进制的,有时候会使用十六进制表示数字,0X+0-9或者a-f来表示. 2.浮点数   浮点数 ...

  5. HDU:2255-奔小康赚大钱(KM算法模板)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2255 奔小康赚大钱 Time Limit: 1000/1000 MS (Java/Others) Mem ...

  6. 数学基础:HUD1124-Factorial(N!末尾0的个数)

    Factorial Problem Description The most important part of a GSM network is so called Base Transceiver ...

  7. SDOJ 1195 Zhenhuan

    描述 今日又在看甄嬛传,皇上觉得后宫们的勾心斗角太险恶了,有点不好,决定给每个妃子发丝带以让后宫之间和睦相处.皇上一共有N个后宫(标号为1~n),站成一个环形(1号与n号相邻),每个后宫想要ai个丝带 ...

  8. js常见的方法

    Ajax请求 jquery ajax函数 我自己封装了一个ajax的函数,代码如下: var Ajax = function(url, type success, error) { $.ajax({ ...

  9. 2章 perl标量变量

    标量变量 单单存储一个值得变量   ,单个标量值 $name   为变量  区分大小写 $barney=$barney*2   第一次  取值  等号右边    :第二次  赋值 等号左边 双目操作符 ...

  10. # Linux 命令学习记录

    Linux 命令学习记录 取指定文件夹下的任意一个文件,并用vim打开 vi $(ls -l|grep "^-"|head -n 1|awk '{print $9}') 统计给定文 ...