SpringBoot自动配置原理流程图
SpringBoot的优势之一是简化了配置,其自动配置原理也是面试高频题之一
下面我们来分析下SpringBoot的自动配置原理

启动类
启动类:
package com.qzcsbj.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ApidemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApidemoApplication.class, args);
    }
}
@SpringBootApplication表示这个类是启动类

@SpringBootApplication是一个复合注解

下面把@SpringBootApplication替换为@SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan,程序一样可以正常启动并访问
package com.qzcsbj.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
// @SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public class ApidemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApidemoApplication.class, args);
    }
}
so,@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
@SpringBootConfiguration
标注在某个类上,表示这是一个SpringBoot的配置类
@SpringBootConfiguration = @Configuration

@Component组件,说明启动类本身也是Spring中的一个组件

@ComponentScan
自动扫描并加载符合条件的组件或者bean,加载到IOC容器中
老写法
<?xml version="1.0" encoding="UTF-8"?>
<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"
       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">
 
    <!--扫描包-->
    <context:component-scan base-package="com.qzcsbj.*"/>
 
</beans>
演示
创建maven项目,添加spring依赖然后创建实体类
package com.qzcsbj.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
 * @description : <描述>
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
public class Person {
    @Value("123")
    private int id;
    @Value("jack")
    private String name;
}
在config下创建TestConfig配置类,指定扫描路径
package com.qzcsbj.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
 * @description : <描述>
 */
@Configuration
@ComponentScan("com.qzcsbj")  // 指定扫描路径
public class TestConfig {
}
除了自己,还扫描到person了(springboot中不需要指定,默认是扫描父包)

测试:TestConfig就相当于以前的xml文件
package com.qzcsbj;
import com.qzcsbj.bean.Person;
import com.qzcsbj.config.TestConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
 * @description : <描述>
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
public class MyTest {
    @Autowired
    Person person;
    @Test
    public void test(){
        System.out.println("person: " + person);
    }
}

@EnableAutoConfiguration
@EnableAutoConfiguration :开启自动配置功能

@AutoConfigurationPackage :自动配置包
@Import(AutoConfigurationImportSelector.class)给容器导入组件(选择器)
其中,重点是@Import(AutoConfigurationImportSelector.class),点击AutoConfigurationImportSelector

点击实现接口DeferredImportSelector,另外下面还实现了BeanClassLoaderAware

点击继承的接口ImportSelector(选择器)

关注下面这个方法

返回到AutoConfigurationImportSelector类,定位到selectImports方法(类中实现了这个方法)
点击getAutoConfigurationEntry方法

该方法中的getCandidateConfigurations方法,返回一个自动配置类的类名列表
debug

configurations这个list存的是所有自动化配置类的全类名,都是AutoConfiguration结尾的,这些是框架已经写好的自动配置类

点击getCandidateConfigurations方法

SpringFactoriesLoader是工具类,点击loadFactoryNames方法

点击loadSpringFactories方法

类加载器,加载类路径是所有META-INF/spring.factories文件

springboot

mybatis

自动配置生效
每一个自动配置类都是在某些条件之下才会生效
@ConditionalOnBean:当容器里有指定的bean的条件下
@ConditionalOnMissingBean:当容器里不存在指定bean的条件下
@ConditionalOnClass:当类路径下有指定类的条件下
@ConditionalOnMissingClass:当类路径下不存在指定类的条件下
比如mybatis

要生效,我们需要导入对应的场景启动器
<dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.0</version>
        </dependency>
点击mybatis-spring-boot-starter
可以看到有如下依赖,导入了下面的依赖,上面条件判断,SqlSessionFactory和SqlSessionFactoryBean就肯定存在了

总结
核心原理:Spring Boot启动的时候会通过@EnableAutoConfiguration注解找到META-INF/spring.factories配置文件中的所有自动配置类,并对其进行加载,这些自动配置类都是以AutoConfiguration结尾来命名的,它实际上就是一个配置类,它能通过以Properties结尾命名的类中取得在全局配置文件中配置的属性,而XxxxProperties类是通过@ConfigurationProperties注解与全局配置文件中对应的属性进行绑定,然后再通过@EnableConfigurationProperties注解导入到Spring容器中。
【bak】
__EOF__
        
本文作者:持之以恒(韧)         
关于博主:擅长性能、全链路、自动化、企业级自动化持续集成(DevOps/TestOps)、测开等            
    










