SpringBoot 自动装配原理详解

发布于:2025-07-21 ⋅ 阅读:(21) ⋅ 点赞:(0)

一、前言

要讲清楚SpringBoot自动装配原理,我们可以分成两个问题进行讲解

1.什么时SpringBoot的自动装配

2.SpringBoot 是如何实现自动装配的?如何实现按需加载?

在学习Spring框架的时候,相信每个人脑海里都浮现过一句话:"要是有代码能够代替xml配置文件就好了!"

因为我们在引入某些功能的或者第三方依赖的时候,还需要显示配置XML和Java

像这样

Spring.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/mvc/ http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.howtodoinjava.demo" />
    <mvc:annotation-driven />

    <!-- JSON Support -->
    <bean name="viewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
    <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>

</beans>

 

@Configuration
public class RESTConfiguration
{
    @Bean
    public View jsonTemplate() {
        MappingJackson2JsonView view = new MappingJackson2JsonView();
        view.setPrettyPrint(true);
        return view;
    }

    @Bean
    public ViewResolver viewResolver() {
        return new BeanNameViewResolver();
    }
}

终于,Springboot来了,SpringBoot我们只需添加相关的依赖,无需配置,通过启动主程序即可

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

并且,我们通过 Spring Boot 的全局配置文件 application.propertiesapplication.yml即可对项目进行设置比如更换端口号,配置 JPA 属性等等。

为什么 Spring Boot 使用起来这么酸爽呢? 这得益于其自动装配。自动装配可以说是 Spring Boot 的核心,那究竟什么是自动装配呢?

二、什么是自动装配?

在Spring框架想使用redis的话,我们需要引入第三方依赖,需要手动配置非常麻烦,但是,在SpringBoot中,我们直接引入一个starter即可。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

 我们进入SpringBoot父项目可以看到:

SpringBoot已经为我们配置了符合该版本的redis

 所以什么是自动装配??

 简单理解:通过注解或者一些简单的配置就能在Springboot 的帮助下实现某块功能

三、SpringBoot是如何实现自动装配的??
 

我们先看一下 SpringBoot 的核心注解 SpringBootApplication 。

 

 

大概可以把 @SpringBootApplication看作是 @Configuration@EnableAutoConfiguration@ComponentScan 注解的集合。根据 SpringBoot 官网,这三个注解的作用分别是:

  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制

  • @Configuration:允许在上下文中注册额外的 bean 或导入其他配置类

  • @ComponentScan:扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类同级及下级所有的类 ,可以自定义不扫描某些 bean。如下图所示,容器中将排除TypeExcludeFilterAutoConfigurationExcludeFilter

@EnableAutoConfiguration 是实现自动装配的重要注解,我们以这个注解入手。

 

EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类。

AutoConfigurationImportSelector类做了些什么??

AutoConfigurationImportSelector类继承体系如下:

 

 

可以看出,AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中

 public String[] selectImports(AnnotationMetadata annotationMetadata) {
  //判断自动装配开关是否打开、、、、、、
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            try {
    //获取所有需要装配的Bean
                AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                configurations = this.<String>removeDuplicates(configurations);
                configurations = this.sort(configurations, autoConfigurationMetadata);
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return (String[])configurations.toArray(new String[configurations.size()]);
            } catch (IOException ex) {
                throw new IllegalStateException(ex);
            }
        }
    }

 ok 现在我们可以打一个断点来debug一下看一看获取符合条件类的过程

 

到这一步可以看到, 共有96个配置内容被读取到了,但是这96个我们都用的到吗??继续向下执行

清除之后我们发现只剩下了20个符合条件的配置文件(或者说用得到的),因为我们在父项目中之引入了 start-web

除了这里我们还可以在 META-INF/spring.factories路径下观看被读取的配置文件

 
 


网站公告

今日签到

点亮在社区的每一天
去签到