SpringBoot3自动配置原理

​​​​​​自动配置

遵循约定大约配置的原则,在boot程序启动后,起步依赖中的一些bean对象会自动注入到ioc容器

看一下我们前面写的代码有没有达到自动配置的效果呢?

SpringBoot3自动配置原理_第1张图片

没有自动,我们写了配置类,写了@Import注解,所以并没有达到自动配置的效果。那怎么办呢?接下来我们通过翻看源码的方式来了解一下SpringBoot自动配置是怎么回事!了解完毕之后我们照葫芦画瓢就可以解决问题!

自动配置-源码分析

程序引入spring-boot-starter-web 起步依赖,启动后,会自动往ioc容器中注入DispatcherServlet

接下来我们验证一下,看它有没有自动注入DispatcherServlet

创建一个SpringBoot工程

这里没有 web起步依赖

 
        
        
            org.springframework.boot
            spring-boot-starter
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

主启动

@SpringBootApplication
public class SpringbootAutoConfigApplication {
​
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringbootAutoConfigApplication.class, args);
        System.out.println(context.getBean("dispatcherServlet"));
    }
}

这时候工程里面没有 web起步依赖 就没有 DispatcherServlet,这里就会报错

SpringBoot3自动配置原理_第2张图片

导入 web起步依赖


    org.springframework.boot
    spring-boot-starter-web

SpringBoot3自动配置原理_第3张图片

那就验证了之前的话,如果你引入了web起步依赖,就会自动往ioc容器中注入一个DispatcherServlet,那SpringBoot如何做到的呢?接下来就要翻一下源码了。

源码解读

@SpringBootApplication 注解

SpringBoot3自动配置原理_第4张图片

我们进入这个注解,它的头上怎么顶着这么多注解,不过真正重要的只有三个注解,我们接下来会 一 一介绍。

@Target(ElementType.TYPE)  //元注解,可以在类上面使用 @Retention(RetentionPolicy.RUNTIME) //元注解,运行时阶段

@Documented  //生成Java文档

@Inherited  //是一个标识,用来修饰注解

SpringBoot3自动配置原理_第5张图片

@SpringBootConfiguration 注解

点进@SpringBootConfiguration注解,可以发现其核心注解为@Configuration注解:

SpringBoot3自动配置原理_第6张图片

@Configuration注解是Spring框架的注解之一,用于标记配置类。 在Spring Boot中,使用@Configuration注解可以将该类作为配置类,从而使该类中的Bean可以被Spring IoC容器管理和使用。

在配置类中,我们可以使用另外两个注解@Bean和@Scope来定义Bean,其中@Bean注解用于定义Bean对象,而@Scope注解用来指定Bean对象的作用域。

总的来说,@Configuration注解能够将一个类定义为Spring Boot应用程序中的配置类,从而使该类中的Bean对象能够被Spring IoC容器进行自动管理和装配。这让应用开发者能够更加专注于应用逻辑的实现,而不必花费精力在繁琐的配置上。 所以@SpringBootConfiguration注解本质上就是一个@Configuration注解,用来标注某个类为 JavaConfig 配置类,有了这个注解就可以在 SpringBoot 启动类中使用@Bean标签配置类了。

@ComponentScan 注解

SpringBoot3自动配置原理_第7张图片

@ComponentScan 是 Spring Framework 中的一个注解,它用于指定 Spring 容器需要扫描和管理的组件。组件是 Spring 中的一个抽象概念,它包括了 Spring Bean、Controller、Service、Repository 等等。通过 @ComponentScan 注解,可以让 Spring 容器自动扫描和管理这些组件,从而简化应用程序的配置和管理。 @ComponentScan 注解有多个参数,可以用于指定要扫描的组件的位置、排除不需要扫描的组件、指定要排除扫描的组件等等。

默认情况下,Spring Boot会自动扫描主应用程序下的所有组件(@Configuration, @Controller, @Service, @Repository等),但是如果你将组件放在其他包下,那么就需要显式地配置扫描目录。

@EnableAutoConfiguration 注解

这是今天的主角中的主角,自动配置实现的核心注解。 点进这个注解可以发现,如下图所示。

SpringBoot3自动配置原理_第8张图片

我们重点来看 @Import(AutoConfigurationImportSelector.class)这个注解。 @Import 注解是 它用于将一个或多个类导入到 Spring 容器中,以便于在应用程序中使用。通过 @Import 注解,我们可以将一些非 Spring 管理的类实例化并注册到 Spring 容器中,或者将一些 Spring 管理的配置类导入到当前配置类中,以便于在应用程序中进行统一的配置和管理。 @Import是Spring Framework 中的一个注解,用于在配置类中导入其他配置类或者普通的Java类。

说白了在这里@Import注解的作用就是将 AutoConfigurationImportSelector 这个类导入当前类,这个类就是实现自动配置的核心。 我们继续进入到 AutoConfigurationImportSelector 类:

AutoConfigurationImportSelector实现了DeferredImportSelector接口,我们进入DeferredImportSelector接口

最后,我们发现, AutoConfigurationImportSelector 实际上是实现了 ImportSelector 接口,这个接口只有两个方法,其中我们需要重点关注 selectImports() 方法。

ImportSelector 接口是 Spring Framework 中的一个接口,它可以用于在 Spring 容器启动时动态地导入一些类到 Spring 容器中。通过实现 ImportSelector 接口,并重写其中的 selectImports 方法,我们可以自定义逻辑来确定需要导入的类,从而实现更加灵活的配置和管理。

SpringBoot3自动配置原理_第9张图片

selectImports 方法是 ImportSelector 接口中的一个方法,用于返回需要导入的类的全限定类名数组。在 Spring 容器启动时,Spring 会扫描所有实现了 ImportSelector 接口的类,并调用其中的 selectImports 方法来确定需要导入的类。

我们进入getAutoConfigurationEntry()方法

SpringBoot3自动配置原理_第10张图片

这里返回AutoConfigurationEntry类,里面传入了 configurations和exclusions两个参数, configurations参数通过getCandidateConfigurations() 方法得到,我们进入getCandidateConfigurations()方法。

SpringBoot3自动配置原理_第11张图片

Assert.notEmpty这是一个断言,configurations不能为空 ,如果为空了,给你一段提示:没有自动配置的类找到,在 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports找到,我们将这端配置简称为 .imports 文件,意思就是说,我要去找自动配置类 去 .imports中找,但是我并没有找到,我们需要关注这个配置文件在什么地方,这里先回到pom.xml文件中

SpringBoot3自动配置原理_第12张图片

进去核心起步依赖,这里面引入了一个:spring-boot-autoconfigure,autoconfigure顾名思义就是自动配置的意思。

SpringBoot3自动配置原理_第13张图片

接下来我们去找到autoconfigure

在这里我们找到了 AutoConfiguration.imports配置文件

SpringBoot3自动配置原理_第14张图片

SpringBoot3自动配置原理_第15张图片

点进去,这个配置文件其实就是配置了一堆类的全类名,这些类都是自动配置类,接下来我们去看看之前演示的DispatcherServlet相关的自动配置类 Ctrl+F:搜索一下

SpringBoot3自动配置原理_第16张图片

进入:DispatcherServletAutoConfiguration类 , Ctrl+Shift+N全局搜索进入这个类

SpringBoot3自动配置原理_第17张图片

@AutoConfiguration(after = {ServletWebServerFactoryAutoConfiguration.class})顾名思义,自动配置的意思

SpringBoot3自动配置原理_第18张图片

@AutoConfiguration点进去,你会发现它也是一个组合注解,组合了一个@Configuration()

SpringBoot3自动配置原理_第19张图片

说白了DispatcherServletAutoConfiguration这个类是一个配置类

SpringBoot3自动配置原理_第20张图片

这个类用了@AutoConfiguration注解,更加见名之意它是一个配置类

SpringBoot3自动配置原理_第21张图片

我们再看@ConditionalOnClass这个注解,是不是很熟悉,前面讲到过:它在这里的意思是,如果你环境里面有DispatcherServlet,那自动配置类就会生效自动注入一个DispatcherServlet的bean对象,如果环境里没有DispatcherServlet,那就不生效,不注入了。

接下来继续往下看

SpringBoot3自动配置原理_第22张图片

这里内部有一个DispatcherServletConfiguration类,也配置@Configuration注解,里面写一个方法,方法最终返回的就是dispatcherServlet,方法上面有@Bean注解,最终我们可以看到,它注入DispatcherServlet的代码在这里,其实你会发现这里的代码和我们之前写的代码并没有很大的区别,都是写一个方法,让后在方法上面声明一个@Bean注解。

这里最核心的是,它把这个类DispatcherServletAutoConfiguration写到指定的配置文件里面了,那么SpringBoot就可以自动的去读取这个全类名,把这个配置的类的对象注入到Ioc容器中,由于这个配置类的内部还有配置类DispatcherServletConfiguration,内部的配置类里面还有一些方法,这些方法声明了@Bean注解,所以SpringBoot它会继续解析,直到把这些@Bean注解的方法都解析到,执行这些方法,然后把返回值注入到IOC容器里。

因此我们自动配置的核心在哪?核心核心,在这个.imports配置文件中,那么源码我们就到这。

小总结

SpringBoot3自动配置原理_第23张图片

在SpringBoot2.7版本以前,它自动配置使用的配置文件是 spring.factories,它会从 spring.factories配置文件中读取配置类的全类名,那么在SpringBoot2.7以后到3.0以前,它同时兼容了.imports配置文件以及spring.factories配置文件,在3.0以后只支持.imports配置文件,这个大家要清楚。

通过源码分析,我们知道了,SpringBoot自动配置无非就是提供一个自动配置类,把这个类名写到指定的配置文件中就可以了。

说一说SpringBoot自动配置原理?

SpringBoot3自动配置原理_第24张图片

希望可以帮到大家,喜欢的给冯宝宝点个关注把,蟹蟹支持!!

你可能感兴趣的:(spring,boot)