SpringBoot:认认真真梳理一遍自动装配原理(中)

简介: SpringBoot:认认真真梳理一遍自动装配原理(中)

SpringBoot会将所有的功能场景都封装成一个一个的启动器,供开发人员使用。


我们在使用的时候也可以直接去官网上找我们所需的启动器,直接将其引入。


获取启动器文档:


https://docs.spring.io/spring-boot/docs/2.2.1.RELEASE/reference/html/using-spring-boot.html#using-boot-starter


主程序(重要)


//@SpringBootApplication 标注,是一个SpringBoot应用
@SpringBootApplication
public class SpringbootdemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootdemoApplication.class, args);
    }
}


再写SpringBoot项目的时候,总要写这么一个主程序,这个主程序最大的特点就是其类上放了一个@SpringBootApplication注解,这也正是SpringBoot项目启动的核心,也是我们要研究的重点。


注意:之后的分析可能会深入源码,源码是一层一层嵌套的,所以光靠文字说明会比较难以理解,最好是自己在IDE环境下跟着一步一步跟着点下去。当然也可以绕过这一部分直接看结论。


点开@SpringBootApplication,可以发现它是一个组合注解,主要是由这么几个注解构成的。


@SpringBootConfiguration//核心
@EnableAutoConfiguration//核心
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })


我们首先要研究的就是核心的两个注解 @SpringBootConfiguration@EnableAutoConfiguration,逐个进行分析。


@SpringBootConfiguration


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}


可以看到SpringBootConfiguration其实就携带了一个@Configuration注解,这个注解我们再熟悉不过了,他就代表自己是一个Spring的配置类。所以我们可以认为:


@SpringBootConfiguration = @Configuration


@EnableAutoConfiguration


顾名思义,这个注解一定和自动配置相关,点进去看源代码之后可以发现,其内部就包含了这么两个注解。


@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationImportSelector.class)//自动配置导入选择


来看看@Import(AutoConfigurationImportSelector.class)中的内容:


它帮我们导入了AutoConfigurationImportSelector,这个类中存在一个方法可以帮我们获取所有的配置,代码如下。


/*
  所有的配置都存放在configurations中,
  而这些配置都从getCandidateConfiguration中获取,
  这个方法是用来获取候选的配置。
*/
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);


getCandidateConfigurations():


这个方法可以用来获取所有候选的配置,那么这些候选的配置又是从哪来的呢?


/*获取候选的配置*/
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;
    }


实际上它返回了一个List,这个List是由loadFactoryNames()方法返回的,其中传入了一个getSpringFactoriesLoaderFactoryClass(),我们可以看看这个方法的内容。


protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    return EnableAutoConfiguration.class;
}


我们看到了一个眼熟的词 —— EnableAutoConfiguration,也就是说,它实际上返回的就是标注了这个类的所有包。标注了这个类的包不就是@SpringBootApplication吗?


所以我们可以得出结论:它兜兜转转绕了这么多地方,就是为了将启动类所需的所有资源导入。


我们接着往下看,它其中还有这么一条语句,是一条断言:


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.");


这个断言的意思是,configurations必须非空,否则就打印一段话,No auto configuration classes found in META-INF/spring.factories,我们把这个逻辑反过来想想。如果这个集合不为空,是不是就代表找到了这个spring.factories并且会去加载这个文件中的内容呢?


带着这个疑问,我们首先找到spring.factories这个文件:


image.png


可以看到里面包含了很多自动配置属性:


image.png


我们可以随便找一个自动配置点进去,比如WebMvcAutoConfiguration


image.png


这里放了所有关于WebMvc的配置,如视图解析器、国际化等等。


分析到这里,我们就可以得出一个完整的结论了:


当我们的SpringBoot项目启动的时候,会先导入AutoConfigurationImportSelector,这个类会帮我们选择所有候选的配置,我们需要导入的配置都是SpringBoot帮我们写好的一个一个的配置类,那么这些配置类的位置,存在与META-INF/spring.factories文件中,通过这个文件,Spring可以找到这些配置类的位置,于是去加载其中的配置。


image.png



相关文章
|
3天前
|
安全 Java 数据安全/隐私保护
SpringBoot实现二维码扫码登录的原理与详细步骤
SpringBoot实现二维码扫码登录的原理与详细步骤
122 1
|
3天前
|
XML Java 开发者
Spring Boot中的bean注入方式和原理
Spring Boot中的bean注入方式和原理
134 0
|
3天前
|
缓存 Java Maven
Spring Boot自动配置原理
Spring Boot自动配置原理
52 0
|
3天前
|
前端开发 搜索推荐 Java
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革
|
2天前
|
Java 开发者 Spring
springboot @RequiredArgsConstructor @Lazy解决循环依赖的原理
【5月更文挑战第16天】在Spring Boot中,@RequiredArgsConstructor 和 @Lazy 是两个有用的注解,它们分别用于简化构造函数的生成和控制Bean的加载时间。下面详细解析这两个注解的概念、优缺点以及在实际应用中的示例。
5 1
|
3天前
|
XML Java 开发者
springboot 启动原理、启动过程、启动机制的介绍
【5月更文挑战第13天】Spring Boot 是一种基于 Java 的框架,用于创建独立的、生产级别的 Spring 应用程序。它的主要目标是简化 Spring 应用的初始搭建和开发过程,同时提供一系列大型项目常见的非功能性特征(如嵌入式服务器、安全性、度量、健康检查和外部化配置)。
18 3
|
3天前
|
XML Java 数据库
【SpringBoot:详解Bean装配】
【SpringBoot:详解Bean装配】
11 3
|
3天前
|
Java
SpringBoot之@Conditional衍生条件装配详解
SpringBoot之@Conditional衍生条件装配详解
|
3天前
|
Java Spring 容器
SpringBoot自动装配原理之@Import注解解析
SpringBoot自动装配原理之@Import注解解析
55 0
|
3天前
|
JSON Java Maven
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析
45 0
Javaweb之SpringBootWeb案例之 SpringBoot原理的详细解析