ChenZhen 搜索
首页 标签 归档 留言板 友链 ChatGPT 提示库 AI工具导航网 🚇开往 关于我

Spring Boot自动装配源码阅读笔记

在传统的 springmvc 项目中,当我们需要使用 mvc 模块、mysql 数据模块、redis 缓存模块的时候。我们需要导入依赖的 jar,然后在 spring 的配置文件中配置dataSource(视图解析器)、(文件上传)、事务管理器等模块。把这些我们需要的模块变成 bean,给 spring 管理。SpringBootSpringBoot在启动时会扫描外部引用 jar 包中的文件,将文件中配置的类型信息加载到Spring容器(此处涉及到JVM类加载机制与Spring。

ChenZhen 2024-09-30T21:16:34

Spring Boot自动装配源码阅读笔记

Spring Boot的自动装配(Auto Configuration)是其核心特性之一,它允许开发者在项目中以最少的配置运行 Spring 应用。这一特性使得开发者无需手动配置大量的 Bean 和组件,Spring Boot 会根据项目中的依赖和应用场景,自动配置合适的 Spring 组件。

什么是自动装配?

未使用自动装配之前

在传统的 springmvc 项目中,当我们需要使用 mvc 模块、mysql 数据模块、redis 缓存模块的时候。我们需要导入依赖的 jar,然后在 spring 的配置文件中配置 dataSourcesqlsessionFactoryinternalResourceViewResolver(视图解析器)、multipartResolver(文件上传)、事务管理器等模块。把这些我们需要的模块变成 bean,给 spring 管理。

SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories 文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot

在了解自动装配之前,我们首先来回顾一下以前的 springMVC 项目。在 MVC 中我们使用容器依赖的bean 的时候需要在 xml 中配置声明才能使用,比如 springmvc 中的以下配置。

web.xml中配置 dispatcherServletfilter

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

没用使用自动装配之前,这些庞杂的web配置是每一个项目必须的。我们首先在pom中引入相关的jar。然后再xml中一遍一遍的配置这些东西。 十分复杂低效。

初步了解自动装配

springboot 是一个脚手架工具,约定大于配置。我们只需要按照 springboot 的规范来开发,就能减少很多配置,当需要开发 web 项目的时候。

第一步:引入web 包的 starter 启动器。这个包就包含了 web 的所需的主要功能,同时能导入springweb 相关的依赖 jar。比如spring,springmvc 的包和 tomcat 的包。点击 pom 可查询。

  <!--springboot的web依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

第二步: 我们启动springboot项目之后,就能看到所有的bean。这些bean在容器加载的时候就会把bean自动加载进来。

@SpringBootApplication(scanBasePackages = "com.thits")
@ImportResource(value = "bean.xml") //装配xml文件配置的bean
 
public class SpringBoot1Application {
 
    public static void main(String[] args) {
        //返回ioc容器
        ConfigurableApplicationContext run = SpringApplication.run(SpringBoot1Application.class, args);
        //获取容器中的所有bean
        String[] beanDefinitionNames = run.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println("bean的名字:"+beanDefinitionName);
        }
    }
 
}

截图可以看到控制台的各种 bean 已经被 spring 容器管理了。 比如 multipartResolverDispatcherServlet、视图解析器、事务管理器等。我们就可以直接使用了,不需要在 xml 中配置这些东西了。

在这里插入图片描述

自动装配、按需加载

在启动类中有一个注解就是 @SpringBootApplication,他有三个子注解,子注解又有其他的注解,搞清楚这些注解的意思就能理解自动装配了。

Spring Boot应用程序的入口通常带有@SpringBootApplication注解。这个注解是一个组合注解,包含了@Configuration@EnableAutoConfiguration@ComponentScan

  • @SpringBootApplication(有三个子注解)
    1. @SpringBootConfiguration
      • @Configuaration
    2. @EnableAutoConfiguration (开启自动注入:有两个子注解)
      • @AutoConfigurationPackage (自动配置包:有一个子注解,import)
        • @Import({Registrar.class})
      • @Import({AutoConfigurationImportSelector.class})
    3. @ComponentScan (组件扫描 作用:包扫描项目包路径)

其中,@EnableAutoConfiguration是自动装配的关键,它启动了自动装配机制。

@Import({Registrar.class}) 注解的源码

/**
	 * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
	 * configuration.
	 */
	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
		}

		@Override
		public Set<Object> determineImports(AnnotationMetadata metadata) {
			return Collections.singleton(new PackageImports(metadata));
		}

	}

@Import({Registrar.class}) 源码的作用就是:主启动类注册到容器,也就是 main 方法所在的包下边,将所有的我们自己的代码中的配置注入的 bean 容器。

通过实现 ImportBeanDefinitionRegistrar,向 Spring 容器中添加 Bean 定义

@Import({AutoConfigurationImportSelector.class}) 注解的源码

源码的第一步就是实现 ImportSelector 接口的 ImportSelector 方法,根据类的全部限定名字把类注入到容器(参见 import 注解的用法),注入了那些类呢?接着看源码

在这里插入图片描述

此处源码是获取自动装配的配置类。获取了138个,在哪里获取接着看。

在这里插入图片描述 这里的代码就能看出来去哪里加载了这些自动装配的类,在factories文件中。

在这里插入图片描述

我们查看 autoconfigure 的 jar 下边的 factories 文件就能看到这些指定的自动装配类全类名了。

在这里插入图片描述

自动装配含义

通过@SpringBootApplication注解的两个Import子注解 ,把spring-boot-autoconfigure-2.6.7.jar和其他包的spring.factories 文件中,EnableAutoConfiguration配置的所有类都装配到spring容器中了。

自动装配扩展原理(Condition按需加载)

springboot自动装配的扩展:两个疑难问题讲解:

问题1

我们查看spring.factories中有当前版本支持的所有配置类,这些配置类都会注入bean吗?

:并不是,之后我们需要导入相对的jar包,这个类是真是存在的,然后才可以自动装配这些bean。

举例说明:在spring.factories中有很多配置类,我们截取这几个来说明

在这里插入图片描述

举例1:我们没有配置 DispatcherServlet,但是会通过自动装配,层层判断来自动创建出DispatcherServlet

在这里插入图片描述

举例2:我们Aop的案例

在这里插入图片描述

问题2

在spring 的 IOC 注入了这些138个配置类,我们怎么使用?

:通过配置使用,约定大约配置。

比如我们使用文件上传。我们怎么知道配置文件上传的文件大小、文件路径等信息。在源码中我们可以看到怎么使用。约定大于配置

springboot默认创建StandardServletMultipartResolver,在源码中如下

在这里插入图片描述 文件上传约定大约配置,我们都知道 ConfigurationProperties 注解的作用是绑定配置文件的值。这里就是约定大于配置。我们只需要按照约定来就行了

在这里插入图片描述

在这里插入图片描述

自动装配总结:

1:springboot 默认加载 spring.factories 中指定的所有 AutoConfiguration

2:根据这些 AutoConfiguration 的源码,在里边的条件 @conditional 判断是否真正的使用这些类。

3:导入的对应 jar 话就使用这些类,并且在绑定的 Properties 根据前缀中指定,然后在配置文件中配置属性

这就是自动装配了。

SpringBoot_第四章(自动装配原理分析)

© 版权声明
😀😃😄😁😆😅🤣😂🙂🙃😉😊😇🥰😍🤩😘😗😚😙😋😛😜🤪😝🤑🤗🤭🤫🤔🤐🤨😐😑😶😏😒🙄😬🤥😌😔😪🤤😴😷🤒🤕🤢🤮🤧🥵🥶🥴😵🤯🤠🥳😎🤓🧐😕😟🙁☹️😮😯😲😳🥺😦😧😨😰😥😢😭😱😖😣😞😓😩😫🥱😤😡😠🤬