• 面试题: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.

  • 相关阅读:
    pyqt教程
    python货币转换
    你写过的最蠢的代码是?——全栈开发篇
    Allegro DFM Ravel Rule Testpoint pad to outline检查
    rabbitMQ 面试题
    SpringBoot的IDEA下创建新项目流程,附带start.spring.io URL error问题的解决
    leetcode42 接雨水
    《学术小白学习之路13》基于DTM和主题共现网络——实现主题时序演化网络分析(数据代码在结尾)
    5款可以在学习和办公上提供帮助的软件
    自己编译静态ffmpeg freetype2 not found问题解决
  • 原文地址:https://blog.csdn.net/m0_67392010/article/details/126620141