2. 原理初探

2.1 pom.xml

父依赖

主要依赖一个父项目,主要管理项目的资源过滤和插件

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

点进去,发现还有一个父依赖

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.2.RELEASE</version>
</parent>

这里才是真正管理SpringBoot应用里所有依赖版本的地方,SpringBoot的版本控制中心;

以后导依赖默认不需要写版本;但是如果导入的包没有在依赖中管理就需要手动配置版本

启动器 spring-boot-starter

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

spring-boot-starter-web:帮我们导入web模块正常运行所依赖的组件。

需要使用什么功能,就只需要找到对应的启动器即可!

2.2 主启动类

默认的主启动类

//SpringBootApplication:标注这个类是一个SpringBoot的应用
@SpringBootApplication
public class Springboot01HelloApplication { public static void main(String[] args) {
//将SpringBoot应用启动
SpringApplication.run(Springboot01HelloApplication.class, args);
} }

注解:

@SpringBootConfiguration:springboot的配置
@Configuration:spting配置类
@Component:说明这也是spring的组件 @EnableAutoConfiguration:自动配置
@AutoConfigurationPackage:自动配置包
@Import(AutoConfigurationPackages.Registrar.class):自动配置‘包注册’
@Import(AutoConfigurationImportSelector.class):自动配置导入 //获取所有的配置
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

获取候选的配置:

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}

@SpringBootApplication

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

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan (excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}

@ComponentScan

它对应XML配置中的元素。

作用:自动扫描并加载所有符合条件的组件或bean,将这个bean定义加载到IOC容器中。

@SpringBootConfiguration

作用:标注在类上,表示这是一个springboot的配置类

继续点进去:

@Configuration
public @interface SpringBootConfiguration {
...
} @Component
public @interface Configuration {
...
}

这里出现的注解及解释:

@Configuration :说明这是一个配置类,配置类就是对应Spring的xml配置文件

@Component:说明启动类本身也是Spring中的一个组件,负责启动应用。

@EnableAutoConfiguration

作用:开启自动配置功能,即以前我们需要自己配置的东西,现在SpringBoot自动帮我们配置。

点进该注解:

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}

这里出现的注解:

@AutoConfigurationPackage:自动配置包

Registrar.class的作用:将主启动类所在包及所有子包里的所有组件扫描到Spring容器中。

@Import(Registrar.class)
public @interface AutoConfigurationPackage {
...
}

@import:表示给容器导入一个组件

@Import(AutoConfigurationImportSelector.class):给容器导入组件

AutoConfigurationImportSelector:自动配置导入选择器,那么它到底导入了哪些组件的选择器呢?

  1. 这个类中有这样一个方法

    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
    getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
    }
  2. 这个方法又调用了SpringFactoriesLoader类的静态方法:

    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
    String factoryTypeName = factoryType.getName();
    return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }
  3. 继续点击查看loadSpringFactories方法

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    MultiValueMap<String, String> result = cache.get(classLoader);
    if (result != null) {
    return result;
    } try {
    Enumeration<URL> urls = (classLoader != null ?
    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
    result = new LinkedMultiValueMap<>();
    while (urls.hasMoreElements()) {
    URL url = urls.nextElement();
    UrlResource resource = new UrlResource(url);
    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
    for (Map.Entry<?, ?> entry : properties.entrySet()) {
    String factoryTypeName = ((String) entry.getKey()).trim();
    for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
    result.add(factoryTypeName, factoryImplementationName.trim());
    }
    }
    }
    cache.put(classLoader, result);
    return result;
    }
    catch (IOException ex) {
    throw new IllegalArgumentException("Unable to load factories from location [" +
    FACTORIES_RESOURCE_LOCATION + "]", ex);
    }
    }
  4. 发现一个多次出现的文件:spring.factories,全局搜索它

spring.factories

​ 我们根据源头打开spring.factories,看到很多自动配置的文件;这就是自动配置根源的所在!

WebMvcAutoConfiguration为例,打开:

​ 可以看到一个个都是JavaConfig配置类,并且都注入了一些bean。

​ 所以,自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将对应的 org.springframework.boot.autoconfigure包下的配置项,通过反射实例化为对应标注了@Configuration的JavaConfig形式的IOC容器配置类,然后将这些汇总成为一个实例并加载到IOC容器。

结论

  1. SpringBoot在启动的时候从类路径META-INF/spring.factories中获取EnableAutoConfiguration指定的值;
  2. 将这些值作为自动配置类导入容器,自动配置类就生效,帮我们自动配置工作;
  3. 整个J2EE的整体解决方案和自动配置都在spring-autoconfigure的jar包中;
  4. 它会给容器中导入非常多的自动配置类(xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好;
  5. 有了自动配置类,免去了我们手动编写配置注入功能组件等工作。

SpringBoot-02-原理初探之主启动类的更多相关文章

  1. SpringBoot无法书写主启动类的情况之一

    首先需要引入 spring-boot-starter-web 依赖[springboot web 项目 启动器 jar包]: 如果使用镜像请确保镜像路径正确,可参看笔者博客园m-yb的maven 安装 ...

  2. SpringBoot-02 运行原理初探

    SpringBoot-02 运行原理初探 本篇文章根据b站狂神编写 pom.xml 2.1.父依赖 其中它主要是依赖一个父项目,主要是管理项目的资源过滤及插件! <parent> < ...

  3. 狂神说SpringBoot02:运行原理初探

    狂神说SpringBoot系列连载课程,通俗易懂,基于SpringBoot2.2.5版本,欢迎各位狂粉转发关注学习. 微信公众号:狂神说(首发)    Bilibili:狂神说Java(视频) 未经作 ...

  4. 2 — springboot的原理

    1.初步探索:第一个原理:依赖管理 发现:这里面存放着各种jar包 和 版本号 这也是:我们在前面第一个springboot项目创建中勾选了那个web,然后springboot就自动帮我们导入很多东西 ...

  5. SpringBoot 02: 初识SpringBoot

    1. SpringBoot 产生原因 spring, springmvc框架使用上的一些缺点: 需要使用的大量的配置文件 还需要配置各种对象 需要把使用的对象放入到spring容器中才能使用对象 需要 ...

  6. SpringBoot之旅第六篇-启动原理及自定义starter

    一.引言 SpringBoot的一大优势就是Starter,由于SpringBoot有很多开箱即用的Starter依赖,使得我们开发变得简单,我们不需要过多的关注框架的配置. 在日常开发中,我们也会自 ...

  7. SpringBoot源码学习系列之启动原理简介

    本博客通过debug方式简单跟一下Springboot application启动的源码,Springboot的启动源码是比较复杂的,本博客只是简单梳理一下源码,浅析其原理 为了方便跟源码,先找个Ap ...

  8. SpringBoot主程序类,主入口类

    主程序类,主入口类 /** * @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用 */ @SpringBootApplication publi ...

  9. springboot系列(三) 启动类中关键注解作用解析

    一.Springboot:请求入口 @SpringBootApplication @EnableAspectJAutoProxy @EnableScheduling @EnableTransactio ...

随机推荐

  1. Android Studio 代码回退

    1.VCS–Local History–Show History 或者 这个按钮 2.代码操作记录出现了,选定我们操作的一个历史阶段 3.点击左上角的按钮(revert),代码回退成功

  2. python 09 数据包 异常处理

    pickle模块操作文件 pickle.dump(obj, file[, protocol]) 序列化对象,并将结果数据流写入到文件对象中.参数protocol是序列化模式,默认值为0,表示以文本的形 ...

  3. ipvsadm服务报错/bin/bash: /etc/sysconfig/ipvsadm: No such file or directory

    问题: 在执行重启ipvsadm服务时报错: 提示没有找到/etc/sysconfig/ipvsadm 解决: [root@lvs1 ~]# ipvsadm --save > /etc/sysc ...

  4. MySQL数据库根据一个或多个字段查询重复数据

    系统在开发测试过程中出现bug,比如并发操作没有处理好,数据库中往往会插入重复数据,这些脏数据经常会导致各种问题.bug可以修改,但是数据往往也要处理,处理SQL如下: 1.根据一个字段查找重复数据 ...

  5. Discovering Reinforcement Learning Algorithms

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:2007.08794v1 [cs.LG] 17 Jul 2020 Abstract 强化学习(RL)算法根据经过多年研究手动发 ...

  6. Java程序员值得拥有的TreeMap指南

    先看再点赞,给自己一点思考的时间,微信搜索[沉默王二]关注这个有颜值却假装靠才华苟且的程序员.本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题 ...

  7. vps的搭建

    最近一直想自己搭建一款vps使用,但是苦于一直没有时间,直到今天得空,与大家一起分享下. 服务商的选择 因为自己之前在 vultr 上还留有余额(60$呢,好几百块大洋呢),所以我的服务商就选择 vu ...

  8. jQuery源码分析系列(二)Sizzle选择器引擎-上

    前言 我们继续从init()方法中的find()方法往下看, jQuery.find = Sizzle; ... find: function (selector) { /** ... */ ret ...

  9. seo如何发外链

    http://www.wocaoseo.com/thread-228-1-1.html 在做外链方面博主并没有什么太多的经验,做为一位seo,下面武汉seo把自己做外链的大条列出来,都是经过本身实践并 ...

  10. OC基础--数据类型与表达式

    前言 做iOS开发有3年了,从当初的小白到现在,断断续续看过很多资料,之前也写过一些博文来记录,但是感觉知识点都比较凌乱.所以最近准备抽时间把iOS开发的相关知识进行一个梳理,主要分为OC基础.UI控 ...