遇一山,过一山,处处有风景;只要勇敢向前,一路尽是繁花盛开。 | (点击查看→)【测试干货】python/java自动化、持续集成、性能、测开、简历、笔试面试等

【面试题】SpringBoot自动配置原理

 

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】

原文已更新:https://www.cnblogs.com/uncleyong/p/17067567.html

 

posted @ 2023-01-26 22:39  全栈测试笔记  阅读(748)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end