Springboot的自动配置原理

一、前言

想必很多小伙伴在面试或者学习springboot的时候或多或少都了解过Springboot的自动配置,我在面试的时候也被问到过,那么这次在公司的项目中也用到了这一块儿知识,比如自动配置类不加@Configuration,而是将这个模块所有的自动配置类全部写到该模块下的spring.factories文件下实现自动配置,那么这里就想要记录一下:

二、SPI

SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。
Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。
多数开发人员可能不熟悉,因为这个是针对厂商或者插件的。在 java.util.ServiceLoader 的文档里有比较详细的介绍。
简单总结下 Java SPI 机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案、xml解析模块、jdbc模块的方案等。面向的对象设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及了具体的实现类,就违反了可插拔的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。
我们来演示一下这种机制
1、首先写一个接口,由于我也玩原神,所以这里举一个原神的小例子:

package mbw;

public interface YuanShen {
    void Attack();
}


2、然后自定义两个实现类实现刚才的接口:

package mbw;

public class Water implements YuanShen {
    @Override
    public void Attack() {
        System.out.println("神里流-水囿");
    }
}

package mbw;

public class Fire implements YuanShen {
    @Override
    public void Attack() {
        System.out.println("蹦蹦炸弹");
    }
}

3、最后要在ClassPath路径下配置添加一个文件。文件名字是接口的全限定类名内容是实现类的全限定类名,多个实现类用换行符分隔。
在这里插入图片描述
效果测试:
可以通过ServiceLoader.load或者Service.providers方法拿到实现类的实例。

package mbw;


import java.util.ServiceLoader;

public class MainClass {
    public static void main(String[] args) {
        ServiceLoader<YuanShen> load = ServiceLoader.load(YuanShen.class);
        //或者Service.providers()方法获取我们的Iterator对象
        //Iterator<YuanShen> providers = Service.providers(YuanShen.class);
        //循环获取所需的对象
        for (YuanShen next : load) {
            next.Attack();
        }
    }
}

结果如图:通过spi机制也可以像我们new对象一样获取实例!
在这里插入图片描述

三、Spring Boot 如何将依赖包中的 bean 注册到容器中?

那么了解了SPI,其实一种Springboot自动配置原理类似的机制就很好理解了:
在 Spring Boot 项目中,怎样将 pom.xml 文件里面添加的依赖中的 bean 注册到 Spring Boot 项目的 Spring 容器中呢?

你可能会首先想到使用 @ComponentScan 注解,遗憾的是 @ComponentScan 注解只能扫描 Spring Boot 项目包内的 bean 并注册到 Spring 容器中,项目依赖包中的 bean 不会被扫描和注册。此时,我们需要使用 @EnableAutoConfiguration 注解来注册项目依赖包中的 bean。而 spring.factories 文件,可用来记录项目包外需要注册的 bean 类名。spring.factories利用了SPI机制,来实现模块的扩展配置。

使用 spring.factories 文件有什么好处呢?假如我们封装了一个插件,该插件提供给其他开发人员使用。我们可以在 spring.factories 文件中指定需要自动注册到 Spring 容器的 bean 和一些配置信息。使用该插件的开发人员只需少许配置,甚至不进行任何配置也能正常使用。

四、实现原理

项目启动时@EnableAutoConfiguration 通过SpringFactoriesLoader 加载所有META-INF下的spring.factories文件,根据EnableAutoConfiguration.class加载所有配置类。

所以说,如果你想让 Spring Boot 自动将你的库的某个类的实例注册到 Spring 容器中,就需要按照其要求提供 META-INF/spring.factories 文件。

我们可以演示一下:
比如现在我新建一个Springboot的项目,然后在里面新建一个类,并写一个简单的方法,注意这里我并没有将它注册进容器:
在这里插入图片描述
然后新建一个Testconfig类,内部我们通过@Bean去将我们刚刚的TestMain类注册为bean,并且调用里面的test方法为后面方便验证,但是这里我同样也没有给这个类加上@Configuration注解标识它为自动配置类,那么按道理是不可能自动配置成功的
在这里插入图片描述
然后就是主角登场
我们在我们的resources下新建META-INF文件夹并新建spring.factories文件,内容如下:
在这里插入图片描述
这样我们就已经完成了之前配置类的自动配置,并且会去执行里面所有的带有@Bean的方法并将返回值注册为Bean.
我们回到TestConfig
可以看到类左边有类似的标记:
在这里插入图片描述
那么下面实践一下
我们新建一个模块,然后将上面的项目作为依赖导入到该模块中:
我们新建一个TestPackage类,注入TestMain这个类
在这里插入图片描述
然后测试,如果之前自动配置成功,那么测试一定会通过
如果自动配置失败,TestMain一定没有注入进容器,那么测试肯定不通过:
在这里插入图片描述
测试通过,那么说明自动配置成功。
大家还可以试一试如果将TestConfig中@Bean去掉,再测试下就会发现失败了,因为TestMain并没有注册进容器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
SpringBoot自动配置原理简述 SpringBoot自动配置SpringBoot的一大特色,它提供了一种简洁的方式来配置应用程序。在SpringBoot中,我们可以通过添加特定的依赖来自动配置应用程序的各种组件,例如数据源、日志、Web服务等。使用自动配置可以大大简化应用程序的配置过程,减少开发人员的工作量,提高开发效率。 自动配置的实现原理是基于Spring的条件化配置机制。SpringBoot会根据应用程序的依赖和当前环境自动配置各种组件。条件化配置可以通过在类上添加@Conditional注解来实现,该注解可以指定一个条件类,只有满足该条件类的条件时,才会进行配置。例如,以下代码示例中,只有当classpath中存在H2数据库驱动程序时,才会自动配置H2的数据源。 @Configuration @ConditionalOnClass(org.h2.Driver.class) public class H2DataSourceAutoConfiguration { // 配置H2数据源 } 除了依赖条件外,SpringBoot还支持很多其他条件,例如环境条件、属性条件、Bean条件等。通过组合这些条件,可以实现更加灵活的自动配置。例如,以下代码示例中,只有当当前环境为开发环境时,才会自动配置开发环境的日志。 @Configuration @Profile("dev") public class DevLoggerAutoConfiguration { // 配置开发环境的日志 } 总之,SpringBoot自动配置机制是基于Spring的条件化配置机制实现的,它可以根据应用程序的依赖和当前环境自动配置各种组件,大大简化了应用程序的配置过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨~旋律

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值