[springboot一本通]-3

*   [三、配置加载原理源码解析](about:blank#_26)

*   [四、@EnableAutoConfiguration 作用](about:blank#EnableAutoConfiguration__54)

*   [五、Bean的自动装配实现原理简述](about:blank#Bean_65)

在本专栏一开始,我们就讲过Spring Boot大量的简化了配置。实际上这些配置还都存在,只是将一些不常用的配置隐藏了起来,不需要我们像以往一样逐一配置,从而减少了配置量、提高了开发效率。本文向大家介绍一下,Spring Boot实现自动配置加载的原理。

一、Bean自动装载的核心问题


我们之前为大家介绍了,Spring Boot里面的各种Bean(类对象)能够实现自动装载,自动的装载帮我们减少了XML的配置,和手动编码进行Bean的加载工作。从而极大程度上帮我们减少了配置量和代码量。

在这里插入图片描述

要实现Bean的自动装载,需要解决两个问题

  • 如何保证Bean自动装载的灵活性?这个问题通过配置文件来解决,在配置A情况下去装载BeanY;在配置B情况下去装载BeanZ。(通常情况下配置A和B会有默认值,来决定默认的装载行为,这样就不需要我们配置了,进一步减少配置量)

  • 如何保证Bean装载的顺序性?当BeanA装载完成之后再去装载BeanY,BeanY装载完成之后才去装载BeanX。这个装载顺序问题由@ConditionOnXXXXXXX注解来解决。

二、全局配置文件


SpringBoot使用一个全局的配置文件,配置文件名是固定的;

  • application.properties

  • application.yml

全局配置文件的作用:修改SpringBoot自动配置的默认值,通过配置来影响SpringBoot自动加载行为。

三、配置加载原理源码解析


所有的Spring Boot应用程序都是以SpringApplication.run()作为应用程序入口的。下面我们来一步一步跟踪一下这个函数。


public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {

    return run(new Class[]{primarySource}, args);

}



public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {

    return (new SpringApplication(primarySources)).run(args);

}



run方法传入了SpringApplication对象和一些运行期参数。继续向前跟进,我们发现一个类叫做SpringFactoriesLoader,这里面体现了Spring Boot加载配置文件的核心逻辑。

在这里插入图片描述

从上图可以看到:

  • META-INF/spring.factories文件夹下下面加载了spring.factories文件资源

  • 然后读取文件中的ClassName作为值放入Properties。

在这里插入图片描述

然后通过反射机制,对spring.factories里面的类资源进行实例化,所以spring.factories文件里面究竟写了什么类?这些类是做什么的?就是我们下一步要探究的问题了。

在这里插入图片描述

四、@EnableAutoConfiguration 作用


SpringBoot入口启动类使用了SpringBootApplication,实际上就是开启了自动配置功能@EnableAutoConfiguration。

在这里插入图片描述

SpringFactoriesLoader会以@EnableAutoConfiguration的包名和类名org.springframework.boot.autoconfigure.EnableAutoConfiguration为Key查找spring.factories文件,并将value中的类名实例化加载到Spring Boot应用中。如下图:

在这里插入图片描述

spring.factories文件中的每一行都是一个自动装配类。

五、Bean的自动装配实现原理简述


每一个自动配置类进行自动配置功能(spring.factories中的每一行对应的类),我们以HttpEncodingAutoConfiguration为例讲解一下:


//加载application全局配置文件内的部分配置到HttpEncodingProperties里面

@Configuration

@EnableConfigurationProperties({HttpEncodingProperties.class}) 

//当web容器类型是servlet的时候执行本类中的自动装配代码

@ConditionalOnWebApplication(

    type = Type.SERVLET

)

//当有一个CharacterEncodingFilter的这样一个类的字节码文件时时执行本类中的自动装配代码

@ConditionalOnClass({CharacterEncodingFilter.class})

//当spring.http.encoding配置值为enabled的时候执行本类中的自动装配代码

@ConditionalOnProperty(

    prefix = "spring.http.encoding",

    value = {"enabled"},

    matchIfMissing = true   //如果application配置文件里面不配置,默认为true

)

public class HttpEncodingAutoConfiguration {

    private final HttpEncodingProperties properties;



    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {

        this.properties = properties;

    }



    @Bean

    //当没有CharacterEncodingFilter这个Bean就实例化CharacterEncodingFilter为一个bean

    @ConditionalOnMissingBean

    public CharacterEncodingFilter characterEncodingFilter() {

        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();

        filter.setEncoding(this.properties.getCharset().name());

        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpEncodingProperties.Type.REQUEST));

        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpEncodingProperties.Type.RESPONSE));

        return filter;

    }



    @Bean

    public HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {

        return new HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer(this.properties);

    }

    

   //此处省略与自动加载无关的代码:HttpEncode的逻辑及其他

}



在配置类加载过程中,大量的使用到了条件加载注解:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值