SpringBoot自动装配原理分析

243 阅读5分钟

✔自从Spring Boot的出现,让Java的基本系统搭建过程变得更简单,不需要关心很多的配置文件,也不需要去关心市面上各版本的包存在版本冲突等等的问题,Spring Boot遵守约定大于配置的开发原则,大大就是减少了人为的配置,简化了项目开发过程。

SpringBoot如何实现的自动装配?SpringBoot中starter的原理?Spring Boot核心注解有哪些? 等等都是值得我们深入了解,也是检测你是否真正的使用过Spring Boot,或者是否对Spring Boot项目具有一定的基础。

🌈今天我们就是来说一下Spring Boot中的自动装配原理,自动装配是Spring Boot中的一个非常重要的,也是非常具有特色的功能,下面就来看一下吧。

自动装配的整个过程分析

SpringBoot自动装配的过程.png

从启动类开始看

说起Spring Boot中的自动装配,首先要从Spring Boot的启动类开始看。

@SpringBootApplication
public class Application {

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

}

这是一个基本的Spring Boot启动类,我们主要看SpringBootApplication这个注解,点进去源码,看一下具体的实现。

SpringBootApplication.png

如上图所示,SpringBootAplication是一个复合注解。,关键看@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan这三个注解:

@SpringBootConfiguration

它实际上就是一个 @Configuration 注解,这个注解大家应该很熟悉了,加上这个注解就是为了让当前类作为一个配置类交由 Spring 的 IOC 容器进行管理,因为前面我们说了,Spring Boot本质上还是Spring,所以原属于Spring的注解@ConfigurationSpringBoot中也可以直接应用。

@ComponentScan

@Configuration注解的话,我们应该不会陌生,用于定义 Spring 的扫描路径,等价于在 xml 文件中配置 <context:component-scan>,假如不配置扫描路径,那么 Spring 就会默认扫描当前类所在的包及其子包中的所有标注了 @Component@Service@Controller 等注解的类。

@EnableAutoConfiguration

@EnableAutoConfiguration才是实现自动装配的核心,翻译为:自动配置的意思,也可以说自动装配,既然是要聊自动装配原理,它是由@AutoConfigurationPackage@Import注解组成的复合注解。

@EnableAutoConfiguration开启自动装配注解

EnableAutoConfiguration.png

简单说下在此之上的注解,如果你在项目自定义过注解的话,就能很好的分辨这几种的概念了,比如自定义日志注解。

@Target

@Target注解就是表明该注解类能够作用的范围,也就是注解在哪,比如:类、方法、接口、参数等,下面是它的一些参数:

参数说明
@Target(ElementType.TYPE)接口、类、枚举、注解
@Target(ElementType.FIELD)字段
@Target(ElementType.METHOD)方法
@Target(ElementType.PARAMETER)方法参数
@Target(ElementType.CONSTRUCTOR)构造函数
@Target(ElementType.LOCAL_VARIABLE)局部变量
@Target(ElementType.ANNOTATION_TYPE)
@Target(ElementType.PACKAGE)

里面的参数是可以多选的,使用方法比如:@Target({ElementType.METHOD,ElementType.TYPE})。

@Retention

@Retention注解是保留说明,也就是表明这个注解的类在哪里保留,它有三个属性:

1️⃣ RetentionPolicy.SOURCE - 这种类型的Annotations只在源代码级别保留,编译时就会被忽略
2️⃣ RetentionPolicy.CLASS - 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
3️⃣ RetentionPolicy.RUNTIME - 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。

@Documented

@Documented注解表明这个注解应该被javadoc工具记录,默认情况下,javadoc是不包括该注解的,但是如果声明注解时指定了@Documented,那么它就会被javadoc之类的工具处理,该注解类型信息也会被包括在生成的文档中。

@Order

@Order标记定义了组件的加载顺序,这个标记包含一个value属性。属性接受整形值。如:1/2 等等。值越小拥有越高的优先级。Ordered.HIGHEST_PRECEDENCE这个属性值是最高优先级的属性,它的值是-2147483648,对应的最低属性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。

@Inherited

用于加强继承效果。

@Import

事实上,@Import注解才是自动装配的核心Import注解导入了AutoConfigurationImportSelector类,使用Import导入的类都会加载到Spring ioc容器中。

AutoConfigurationImportSelector

AutoConfigurationImportSelector类实现了诸多接口,有:DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered,自动装配的实现逻辑其实就是在selectImports()方法中,如图所示:

AutoConfigurationImportSelector.selectImports.png

继续分析源码,有一个getCandidateConfigurations方法,进入看一下代码情况,上图看到一个getAutoConfigurationEntry()获取自动配置入口的方法,点击进入方法:

image.png

找到getCandidateConfigurations方法:

getCandidateConfigurations.png

这里存在一个断言,意思是当无法正确的找到spring.factories文件时,会报: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.

这个方法其实就是加载spring.factories文件,我们可以看看这个文件都有哪些具体内容,通过IDEA的当前类定位进行寻找,如图所示:

image.png

我们可以看看spring.factories文件的内容:

spring.factories.png

可以看出,通过selectImports方法,取到该文件下的一系列类名,随后将这些类自动加载至IOC容器中,实际上这些类都属于内部存在自动配置的类,同样可以发现这些类名都是以AutoConfiguration结尾的。

总结

Spring Boot自动装配原理实际上就是通过@EnableAutoConfiguration注解,加载AutoConfigurationImportSelector类中的selectImports方法,进而扫描MATE-INF下的spring.factories文件下的自动配置类,并将其装配至Spring IOC容器的过程。