【面试】SpringBoot自动装配原理

1,727 阅读2分钟

@SpringBootApplication

首先我们SpringBoot的入口,即启动类是由@SpringBootApplication注解来标识的,@SpringBootApplication注解的核心组成主要是由以下三个注解组成的

image.png

@SpringBootConfiguration:就是一个@Configuration注解,代表当前是一个配置类,也是一个Spring组件。

image.png

@EnableAutoConfiguration

@EnableAutoConfiguration也是组合注解,由@AutoConfigurationPackage@Import组成。

image.png

我们先来看一下@AutoConfigurationPackage注解(自动配置包),里面是一个@Import注解,导入了一个Registrar.class类(包注册),我们来看看Registrar类会做什么操作?

image.png

image.png

执行了一个registerBeanDefinitions()方法,其实就是通过这个注解来扫描主启动类下的包和子包下的所有组件并加载到 Spring 容器。

下面我们来分析第二个@Import注解,首先会执行一个selectImports()的方法,批量导入组件,具体需要导入哪些组件,通过getAutoConfigurationEntry()这个方法来获取的,所以我只需要搞清楚这个方法做的事情就ok了,

image.png

image.png

getAutoConfigurationEntry()这个方法中,通过getCandidateConfigurations()方法获取所有候选组件,然后做一些去重,移除的操作,最后封装返回一个配置集合。getCandidateConfigurations()这个方法就是利用工厂来加载得到所有组件,启动的时候默认加载所有组件,最终会按需装配,比如你的AOP相关组件,如果你没有使用到AOP,是不会去进行装配的。

image.png

然后通过 SpringFactoriesLoader.loadFactoryNames() 方法扫描到 META-INF/spring.factories 的jar包。并且将需要的自动配置包加载到 Spring 容器中,找到这个 spring.factories 文件:

image.png

就在这里找到了自动配置类并且加载到了 Spring 容器中,完成自动配置类的加载。其实在这个地方我们在开发中就很熟悉了,来我举个例子:

我们在做微服务开发的时候,我们会有这么一个功能,记录一些操作日志,我们一般都会采用AOP的方式来实现,此时我们会单独新建一个Log日志切面模块,其实就是封装了一个组件,在我们需要使用的时候拿来用即可,达到了解耦的目的,但是我们这个Log组件我们要在其他服务中进行引入才能使用,当我们在pom里面引入的时候,只是把这个组件引入了,它里面的核心组件没办法引入,这个时候我们是这么做的,在Log组件的resource下面创建一个META-INF文件夹,再创建一个配置文件spring.factories,将我们Log中需要调用的组件类名,按照逗号分隔编写进去,这样其服务引入Log模块之后,启动的时候就能够自动扫描加载到Spring容器中。

image.png

总结:Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载。

@ComponentScan:包扫描,指定扫描哪些包。