SpringBoot自动装配原理

170 阅读3分钟

一、引入

SpringBoot以其强大的自动装配功能简化了应用搭建的复杂性,让开发者能够更高效地构建应用。那么,SpringBoot是如何实现这种“智能配置”的呢?本文将深入探讨SpringBoot的自动装配原理,并且探讨为什么当多模块下,需要使用其他模块时需要配置META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(SpringBoot2.7以前需要配置META-INF/spring.factories)?

二、流程图

在这里插入图片描述

三源码解读

3.1启动类一般是这样的

@SpringBootApplication
@MapperScan("cn.zc.system.mapper")//本行具体后续会讲解,先主要讲解SpringBootApplication
public class OjSystemApplication {
    public static void main(String[] args) {
        // 启动 Spring Boot 应用
        SpringApplication.run(OjSystemApplication.class, args);
    }
}

3.2 @SpringBootApplication注解: 这个注解是一个复合注解,它包括了@EnableAutoConfiguration,而@EnableAutoConfiguration又导入了AutoConfigurationImportSelector类。 本文我们主要讲下自动配置,关注@EnableAutoConfiguration这个注解

......
@SpringBootConfiguration
@EnableAutoConfiguration
.....
public @interface SpringBootApplication {
}

3.3 @EnableAutoConfiguration 常用于启用自动配置功能。它会根据类路径中的依赖和配置文件中的设置,自动配置 Spring 应用的基础设施,比如数据源、视图解析器等。

.....
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
.....
public @interface EnableAutoConfiguration {
}

重点便是这两个注解,我们接下来详细对这两个注解进行解析

  1. @AutoConfigurationPackage 作用:自动将当前包及其子包注册为 Spring 的组件扫描包。这样,Spring 会自动扫描这些包中的组件并加载到应用上下文中。

  2. @Import({AutoConfigurationImportSelector.class}) 作用:自动加载和注册配置类。

3.3.1 @Import({AutoConfigurationPackages.Registrar.class}) 中核心的代码:

       //方法的作用功能:给容器中批量导入一些组件 
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            //获取到所有需要导入到容器中的配置类
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            // 去重
            configurations = this.removeDuplicates(configurations);
            // 获取需要排除的列表
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            // 移除需要排除的数据
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            // 获取配置过滤器
            configurations = this.getConfigurationClassFilter().filter(configurations);
            // 触发导入自动配置事件
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            // 返回自动配置对象
            return new AutoConfigurationEntry(configurations, exclusions);
        }
    }

让我们追进 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

在这里插入图片描述 注意!接下来,得到所有需要设置为Bean的类!

 public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
        Assert.notNull(annotation, "'annotation' must not be null");
        ClassLoader classLoaderToUse = decideClassloader(classLoader);
        String location = String.format("META-INF/spring/%s.imports", annotation.getName());
        Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
        List<String> importCandidates = new ArrayList();

        while(urls.hasMoreElements()) {
            URL url = (URL)urls.nextElement();
            importCandidates.addAll(readCandidateConfigurations(url));
        }

        return new ImportCandidates(importCandidates);
    }

这是引入的jar包需要的bean 在这里插入图片描述 这是其他模块的路径,根据 在这里插入图片描述 3.3.2 @AutoConfigurationPackage

在这里插入图片描述

4、使用注意事项

虽然SpringBoot的自动装配功能强大且方便,但在使用时还是需要注意以下几点:

避免自动配置冲突:有时候,自动配置可能会与你的手动配置冲突。例如,如果你在配置文件中定义了一个DataSource Bean,而SpringBoot又尝试自动配置一个DataSource Bean,这可能会导致冲突。此时,你可以使用@Primary注解来指定优先使用的Bean,或者使用@EnableAutoConfiguration(exclude={...}来排除某些自动配置类。

注意依赖版本:确保你使用的SpringBoot版本与其他依赖的版本兼容。不兼容的版本可能导致自动装配失败或出现异常行为。

仔细阅读文档:SpringBoot的官方文档非常详尽,包含了大量关于自动装配的信息和示例。在遇到问题时,首先应该查阅官方文档。

5、小结

配合@EnableAutoConfiguration注解使用时,它主要扮演的是配置查找器的角色。这个注解利用其自身的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为搜索的关键词(Key),来定位并加载一组相关的@Configuration类。

因此,@EnableAutoConfiguration的大致自动配置流程可以描述为以下几个步骤:

首先,它会在classpath中扫描所有的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports配置文件。 接着,它会从这些配置文件中提取所有以org.springframework.boot.autoconfigure.EnableAutoConfiguration为key的配置项(注意,这里的key应严格匹配,包括大小写,且不应有笔误,如EnableautoConfiguration应为EnableAutoConfiguration)。 最后,通过Java反射机制,它会实例化那些标注有@Configuration注解的Java配置类,这些类采用JavaConfig的方式定义了IoC容器的配置。完成实例化后,这些配置会被统一注册到Spring的IoC容器中,从而完成了自动配置的过程。