学习 SpringBoot 自动配置之前我们需要一些前置知识点:

Java注解,看完就会用

学会@ConfigurationProperties月薪过三千

不是银趴~是@Import!

@Conditional+@Configuration有没有搞头?


首先我们提出2个问题:

SpringBoot 是干什么的?

是用来简化 Spring 原生的复杂的 xml 配置的进阶框架。

自动配置是什么?

我们用另外一个问题回答这个问题。

我们在 SpringBoot 开发中,就写了几个配置,怎么连接上的数据库?

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://192.0.0.1:3306/test?useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root

在新手村时期,我们照着教程生搬硬抄的时候可能也想过这个问题,今天就来简单探究一下。

再次强调:

看明白本篇内容需要前置知识点,尤其是 @Import 注解。

这一切都要从 @SpringBootApplication 注解讲起。

@SpringBootApplication

@SpringBootApplication 注解是一个复合注解,它由如下三个注解组成。

@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 {
}
@SpringBootApplication
├── @ComponentScan
├── @SpringBootConfiguration
│   └── @Configuration
└── @EnableAutoConfiguration
    ├── @Import(AutoConfigurationImportSelector.class)
    └── @AutoConfigurationPackage
        └── @Import(AutoConfigurationPackages.Registrar.class)

@SpringBootConfiguration

@ComponentScan

@EnableAutoConfiguration

从注解的中文意思中也可以看出来,第三个 @EnableAutoConfiguration 是与我们自动配置紧密相关的。

我们先快速搞定前2个。

@SpringBootConfiguration

这个最简单,把头套摘下来,他就是一个普普通通的 @Configuration 注解包装而成而已,表示当前类是一个配置类。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration // 本体在这
public @interface SpringBootConfiguration {
}

@ComponentScan

可以指定basePackageClasses或basePackages(或其别名value)来定义要扫描的特定包。如果没有定义特定包,扫描将从声明此注解的类的包开始。

顾名思义就是扫描Component。

扫描哪里?

可以通过该注解的属性指定Spring应该扫描的包。如果没有指定包,则默认扫描声明 @ComponentScan 的类所在的包及其子包。

哪些Component?

使用 @Component, @Service, @Repository, @Controller 等注解的类。

扫描了做什么用?

将扫描到的组件注册为Spring的Bean,加入到ioC容器进行统一管理。

@EnableAutoConfiguration

这是自动配置的核心注解!

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}    

我们能看到,其中有2个注解:

@AutoConfigurationPackage

@Import(AutoConfigurationImportSelector.class)

@AutoConfigurationPackage

我们再点进去看一下,发现它又是一个 @Import 。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage { }

@Import(AutoConfigurationPackages.Registrar.class) 中的 Regisgrar 类如下:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata metadata,
                                        BeanDefinitionRegistry registry) {
        register(registry, new PackageImport(metadata).getPackageName());
    }     @Override
    public Set<Object> determineImports(AnnotationMetadata metadata) {
        return Collections.singleton(new PackageImport(metadata));
    } }

如果你有去好好看 @Import 注解的那篇文章,就会知道这是 ImportBeanDefinitionRegistrar 接口实现的方式。

这种方式提供一种手动方式灵活注册 bean。

在这里,我们根据两个提示就可以知道其功能:

• @AutoConfigurationPackage 是自动配置包的意思

• register(registry, new PackageImport(metadata).getPackageName()); 根据包名注册 bean

总结一下就是:

根据通过注解提供的元数据,动态地向 Spring 容器中注册特定包中的类作为 beans。

@Import(AutoConfigurationImportSelector.class)

如果你有去好好看 @Import 注解的那篇文章,就会知道这是 ImportSelector接口实现的方式。

这种方式只需实现 selectImports 方法,并以数组的形式返回要导入的类名,即可实现批量注册组件。

AutoConfigurationImportSelector 类中通过自己的源码实现了如下一个功能:

把 spring-boot-autoconfigure 依赖中 META-INF/spring.factories 文件中需要自动配置的类名读取到数组中。

它长这个样子:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
...

那它到底怎么读取的?

这里我们不讨论具体实现,有兴趣有实力的可以扒源码自己看一下。

当然这些类不会全部都用到,经过筛选,去除重复、去除相应功能模块未开启的配置类、去除人为exclude掉的,将剩余的最终配置类全类名String数组返回。

最后我们再来回收一下开始的那个问题。

我们在 SpringBoot 开发中,就写了几个配置,怎么连接上的数据库?

我们简单捋一下:

SpringBoot 启动。

@SpringBootApplication 注解生效。

@EnableAutoConfiguration 注解生效。

@Import(AutoConfigurationImportSelector.class) 注解生效。

读取到了org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration。

注册一个数据源bean。

读取到 xml 的数据源配置。

大功告成!


往期推荐:

● 终于搞懂动态代理了!

● 学会@ConfigurationProperties月薪过三千

● 学一点关于JVM类加载的知识

● Java注解,看完就会用

● Java反射,看完就会用

● @Value是个什么东西

0.o?让我看看怎么个事儿之SpringBoot自动配置的更多相关文章

  1. springboot2.0.3源码篇 - 自动配置的实现,发现也不是那么复杂

    前言 开心一刻 女儿: “妈妈,你这么漂亮,当年怎么嫁给了爸爸呢?” 妈妈: “当年你爸不是穷嘛!‘ 女儿: “穷你还嫁给他!” 妈妈: “那时候刚刚毕业参加工作,领导对我说,他是我的扶贫对象,我年轻 ...

  2. 【转】Sqlite 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该...

    开发环境: vs2010+.net framework 4.0+ System.Data.SQLite.DLL (2.0)今天在做Sqlite数据库测试,一运行程序在一处方法调用时报出了一个异常 混合 ...

  3. SQLite.dll混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。

    其他信息: V5.7.4.4 Can't find the System.Data.SQLite.dll more info : 混合模式程序集是针对"v2.0.50727"版的运 ...

  4. Spring Boot自动配置源码解析(基于Spring Boot 2.0.2.RELEASE)

    在Spring Boot官方介绍中,首一段话是这样的(如下图).我们可以大概了解到其所表达的含义:我们可以利用Spring Boot写很少的配置来创建一个非常方便的基于Spring整合第三方类库的单体 ...

  5. C#连接Sqlite 出现:混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。的解决方案

    C#连接Sqlite 出现: 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集.的解决方案 C#连接sqlite数据库代码 ...

  6. c# .netframwork 4.0 调用 2.0时报错 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。

    “System.IO.FileLoadException”类型的未经处理的异常在 XXX.dll 中发生 其他信息: 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的 ...

  7. 混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集。

    在调用部分三方库时,由于三方库是基于.NET2.0的.所以在4.0的程序中无法加载.解决方案如下: 在配置文件中添加以下配置 <?xml version="1.0"?> ...

  8. 【原生态跨平台:ASP.NET Core 1.0(非Mono)在 Ubuntu 14.04 服务器上一对一的配置实现-篇幅1】

    鸡冻人心的2016,微软高产年. build 2016后 各种干货层出不穷. 1 Win10 集成了bash  ,实现了纳德拉的成诺,Microsoft Love Linux!!! 2 跨平台  ,收 ...

  9. Webstorm10.0.3破解程序及汉化包下载、Webstorm配置入门指南

    核心提示: WebStorm 是jetbrains公司旗下一款JavaScript 开发工具.被广大中国JS开发者誉为“Web前端开发神器”.“最强大的HTML5编辑器”.“最智能的JavaSscri ...

  10. OpenCV3.0.0+win10 64位+vs2015环境的下载,安装,配置

    操作系统:WIN10 pro 64 软件版本:VS2015+OpenCV3.0.0   1. 下载安装 http://opencv.org/ https://www.visualstudio.com/ ...

随机推荐

  1. (Good topic)哈希表:最长回文串(3.19 leetcode每日打卡)

    给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串. 在构造过程中,请注意区分大小写.比如 "Aa" 不能当做一个回文字符串. 注意: 假设字符串的长度不 ...

  2. Windows之——pid为4的system进程占用80端口的解决办法

    因为Apache无法启动的原因,用netstat命令查看了一下80端口是否被占用了,如下 C:\Users\Maple>netstat -ano | findstr 0.0.0.0:80 TCP ...

  3. 通过计算巢轻松部署Salt服务

    SaltStack服务实例部署 概述 Salt基于Python构建,是一个事件驱动的自动化工具和框架,用于部署.配置和管理复杂的IT系统.使用Salt来自动化公共基础设施管理任务,并确保基础设施的所有 ...

  4. python内置模块——logging

    内置模块-logging loging模块是python提供的内置模块,用来做日志处理. 日志等级: 等级 释义 级别数值 CRITICAL(fatal) 致命错误,程序根本跑不起来 50 ERROR ...

  5. 【JSOI2008】火星人 (哈希+Splay)

    题目 这种含有修改操作的就难以用后缀数组实现了,求LCP这种区间相等的类型可以想到用hash判断,同时LCP的答案大小符合二分条件可以二分求出,如果只有修改可以用线段树维护,因为还有有插入操作所以想到 ...

  6. 将 .NET Aspire 部署到 Kubernetes 集群

    使用Aspirate可以将Aspire程序部署到Kubernetes 集群 工具安装 dotnet tool install -g aspirate --prerelease 注意:Aspirate ...

  7. zookeeper JavaApi 删除节点

    /* * 删除节点 * 1.删除单个节点 * 2.删除带有子节点的节点 * 3.必须成功的删除 * 4.回调 * * */ @Test public void delete1() throws Exc ...

  8. C++学习笔记九:值,常量,常表达式和常初始化

    1. 值: Literal: Data that is directly represented in code without going through some other variable s ...

  9. 16级C程序设计竞赛C题

    问题 C: 回文 时间限制: 1 Sec  内存限制: 128 MB提交: 74  解决: 36[提交][状态][讨论版] 题目描述 给定一个字符串,你可以对字符串做任意改动,你可以在任意地方增加一个 ...

  10. Nginx服务器常用参数设置

    Nginx作为一个高性能的Web服务器和反向代理,它的性能可以通过调整底层操作系统的参数来进一步优化.以下是一些常见的操作系统级别的调整,通常针对Linux系统: File Descriptors L ...