• 面试题:SpringBoot 自动装配原理


    1. @SpringBootApplication注解

    首先,我们都知道SpringBoot程序的入口是通过@SpringBootApplication注解修饰的一个类,例如:

    @SpringBootApplication
    public class DemoApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConfigApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    那么这个自动装配的过程肯定就是通过@SpringBootApplication这个注解内部实现来完成的。看一下它的源码:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = {
    		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
    ....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    @SpringBootApplication这个注解其实是一个复合注解,主要由以下几个部分组成:

    • @Target用于设定注解使用范围,这里表明@SpringBootApplication注解可用于类或者接口上。@Retention表明是运行时注解,@Documented表明这个注解应该被 javadoc工具记录,@Inherited表明继承类也可以使用该注解;
    • @SpringBootConfiguraion表示要加载SpringBoot相关的一些配置;
    • @EnableAutoConfiguration注解用于自动装配,下面细讲;
    • @ComponentScan表明需要扫描的包;
    2. @EnableAutoConfiguration注解

    这里重点就是这个@EnableAutoConfiguration注解,它也是一个复合注解。看一下它的源码:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    	....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    (1)其中@Import(AutoConfigurationImportSelector.class)这个注解就是用于自动导入AutoConfigurationImportSelector这个类
    (2)然后AutoConfigurationImportSelector的selectImports()方法通过SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包。其实每一个可以自动装配的jar里都有一个这样的spring.factories文件。
    (3)接着就根据这个spring.factories文件里配置的所有JavaConfig自动配置类的全限定名,找到所有对应的class,然后将所有自动配置类加载到Spring容器中。spring.factories文件示例如下:

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=
    
    • 1
    • 2

    org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,
    org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,
    org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,
    org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
    org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,
    org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration

    3. application.properties.yml 配置加载

    此外,我们通过application.properties.yml配置文件配置的键值对属性是通过相关联的某个AutoConfiguration类
    (1)比如application.properties.yml中的server.port=8000这个配置,就是通过ServletWebServerFactoryAutoConfiguration类加载的,这个类就是专门加载Servlet相关配置的一个自动装配类。看一下它的源码:

    @Configuration
    @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
    @ConditionalOnClass(ServletRequest.class)
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @EnableConfigurationProperties(ServerProperties.class)
    @Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
    		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
    		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
    		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
    public class ServletWebServerFactoryAutoConfiguration {
    	......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (2)然后这个ServletWebServerFactoryAutoConfiguration类通过@EnableConfigurationProperties({ServerProperties.class})这个注解来将配置文件中的属性注入到ServerProperties中:

    @ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
    public class ServerProperties {
    	private Integer port;
    	......
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (3)这个ServerProperties类的属性注入完成之后,又加载到了ServletWebServerFactoryAutoConfiguration类中,然后在SpringBoot启动时就可以获取到配置的端口号了。


    THE END.

  • 相关阅读:
    Java开发学习(四十一)----MyBatisPlus标准数据层(增删查改分页)开发
    代码随想录 第八章 二叉树02
    【“在路上”疫情信息检测】——项目页面搭建
    大火的4D Radar数据集及基线模型汇总
    ElementUI搭建使用过程
    数藏API对接
    Pytorch_basics_main
    Java 11 的特性详解
    计算机毕业论文选题java毕业设计软件源代码strust2+mybatis客户关系系统[包运行成功]
    JSP session的生命周期简介说明
  • 原文地址:https://blog.csdn.net/m0_67392010/article/details/126620141