03-SpringBoot 自动配置

1.自动配置介绍

SpringBoot通过场景启动器, 帮我们自动配置许多组件
在这里插入图片描述

自动配好Tomcat

  • 引入Tomcat依赖。
  • 配置Tomcat

自动配好SpringMVC

  • 引入SpringMVC全套组件
  • 自动配好SpringMVC常用组件(功能)

自动配好Web常见功能,如:字符编码问题

  • SpringBoot帮我们配置好了所有web开发的常见场景

我们在主类里打印我们的组件看看
MainApplication

package com.limi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {

        //1、返回我们IOC容器
        ConfigurableApplicationContext run = SpringApplication.run(MainApplication.class, args);

        //2、查看容器里面的组件
        String[] names = run.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }
    }
}

在这里插入图片描述

2.默认的包结构

  • 主程序(启动类)所在包及其下面的所有子包里面的组件都会被默认扫描进来
  • 无需SSM的包扫描配置
  • 想要改变扫描路径
    • 在启动类上@SpringBootApplication(scanBasePackages=“com.limi”)
      或者
    • 在配置类中使用@ComponentScan 指定扫描路径

如下图, HelloController在启动类MainApplication的子包下, 所以能被自动扫描
而TestController不在启动类MainApplication所在包及其下面的所有子包里面, 所以不能被自动扫描,
这时就需要手动填写配置改变扫描路径
在这里插入图片描述

3. spring-boot-autoconfigure

SpringBoot所有的自动配置功能都在 spring-boot-autoconfigure 包里面, 我们点开包里的文件看看
在这里插入图片描述
在这里插入图片描述

4.自动装配原理

1.流程图

在这里插入图片描述
简化图
在这里插入图片描述

2.源码分析

在这里插入图片描述
自动装配起源于@SpringBootApplication
在这里插入图片描述
@ComponentScan指定要扫描的包
@SpringBootConfiguration里包含@Configuration, 把类注册为配置类
在这里插入图片描述
@EnableAutoConfiguration

在这里插入图片描述
@AutoConfigurationPackage
通过@Import({Registrar.class})将Registrar这个类注册为组件并导入IOC容器中
在这里插入图片描述
利用Registrar类给容器里面批量注册组件的类
我们看看这个Registrar类
在这里插入图片描述

metadata:注解的原信息,指的是注解被标记在哪里,值是多少等等

方法体作用就是,先根据注解的原信息获得主类即标记了@SpringBootApplication注解的类所在包的包名即代码(new AutoConfigurationPackages.Packagelmports(metadata).getPackageNames(),然后封装在一个数组里面即代码toArray(new String[0]),然后进行注册即代码register(),也就是说register方法就是把某一个包下的所有组件批量注册进来。这也就对应上了为什么默认组件扫描的包名是主类所在包的包名.

回到之前的@EnableAutoConfiguration
在这里插入图片描述

我们看看这个类
在这里插入图片描述

类中通过通过@Import({AutoConfigurationImportSelector.class})将AutoConfigurationImportSelector这个类注册为组件并导入IOC容器中
看看AutoConfigurationImportSelector这个类
在这里插入图片描述
public String[] selectImports(AnnotationMetadata annotationMetadata) 方法规定导入哪些东西
this.getAutoConfigurationEntry(annotationMetadata)给容器中批量导入一些组件
进入this.getAutoConfigurationEntry(annotationMetadata)方法实现看看
在这里插入图片描述
this.getCandidateConfigurations(annotationMetadata, attributes); 获取所有候选的默认的自动导入的配置
进入this.getCandidateConfigurations(annotationMetadata, attributes)方法实现看看
在这里插入图片描述
SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
使用Spring的工厂加载器加载一些东西

进入SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());的方法实现看看
在这里插入图片描述
看到return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
进入loadSpringFactories方法实现
在这里插入图片描述
从META-lNF/spring.factories这个位置来加载一个文件即spring.factories.文件,相当于默认扫描当前系统里面所有这个位置的文件,也就是Spring BootI项目引入的每个jar包的这个位置,有就扫描,没有就跳过

直到扫描到spring-boot-autoconfigure-2.3.4,jar这个包的spring.factories.文件,进入之后发现个配置项EnableAutoConfiguration,后面都是一个全类名加一个换行符的形式,都是xxxxAutoConfiguration类,这些就是SpringBoot兼容的全场景的自动配置,共计131个全类名
在这里插入图片描述

3.总结

1.SpringBoot先加载所有的自动配置类 xxxxxAutoConfiguration

  • 生效的配置类就会给容器中装配很多组件

  • 只要容器中有这些组件,相当于这些功能就有了

  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值。(xxxxProperties里面读取,xxxProperties和配置文件进行了绑定)
    就比如aop
    在这里插入图片描述
    可以看到虽然SpringBoot初始会加载所有的自动配置类, 但是这些配置类生效是有条件控制的, 如果条件不满足, 这个配置类就是一个空壳子, 里面的方法体都不会生效起作用.
    在这里插入图片描述
    aop配置生效的条件就是spring.aop.auto=true
    所以要想使aop自动配置生效, 就需要在配置文件中设置如下

application.properties

spring.aop.auto=true

在application.properties设置debug=true

spring.aop.auto=true
debug=true

可以在运行项目打印出哪些组件生效了,哪些没生效, 而且有其条件原因解释

Positive matches生效组件
在这里插入图片描述
可以看到aop的配置是生效了的

Negative matches未生效组件
在这里插入图片描述

2.定制化配置, 你觉得自动配置的功能不是你想要的,可以去修改覆盖掉框架预设的配置
比如我们要修改字符编码

  • 方法1:用户直接自己用@Bean替换底层的组件

找到HttpEncodingAutoConfiguration.class
在这里插入图片描述

在我们的配置类中编写bean覆盖系统组件
MyConfig

package com.limi.config;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.context.annotation.*;
import org.springframework.web.filter.CharacterEncodingFilter;


@Configuration
public class MyConfig {

    @Bean
    public CharacterEncodingFilter characterEncodingFilter(){
        CharacterEncodingFilter  filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding("GBK");
        return filter;
    }
}
  • 方法2(推荐): 用户去看这个组件是获取的配置文件什么值就去修改。
    xxxxxAutoConfiguration —> 组件 —> xxxxProperties里面拿值 ----> application.properties

我们看看HttpEncodingAutoConfiguration.class给我们预设的编码

    @Bean
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
        return filter;
    }

filter.setEncoding(this.properties.getCharset().name());这不就是从配置文件中取值吗

所以我们直接修改配置文件即可
application.properties

server.servlet.encoding.charset=GBK
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值