SpringBoot自动装配原理

面试官:谈谈你对Springboot自动装配的了解叭

 

回答:

它是starter的基础,也是Spring Boot 的核心,可以简单概括为:通过注解或者一些简单的配置就能在 Spring Boot 的帮助下实现某块功能。

(1)SpringBoot核心注解SpringBootApplication是由几个注解组成的,其中比较重要的一个EnableAutoConfiguration注解

(2)引导类上开启@EnableAutoConfiguration,其内部通过@import注解引入ImportSelector方法

(3)查找工程jar包中META-INF/spring.factories文件

(4)装载内部的对象到容器

 

 

在编写SpringBoot项目时,@SpringBootApplication是最常见的注解了,我们可以看一下里面的源代码:

  • 这里面包含了:
  1. @SpringBootConfiguration
    • 我们点进去通过源码得知他是一个@Configuration,所以也就是对spring原生注解的封装
  2. @EnableAutoConfiguration
  3. @ComponentScan
    • 默认扫描的是与该类同级的类或者同级包下的所有类,是spring的原生注解之一

@EnableAutoConfiguration重头戏——自动装配核心

  • 一旦加上此注解,那么将会开启自动装配功能,容易点讲,Spring会试图在自己的classpath(类路径)下找到所有配置的Bean然后进行装配。
  • 装配Bean时,会根据若干个(Conditional)定制规则来进行初始化。我们看一下它的源码:

  • 导入了自动装配类,AutoConfigurationImportSelector.class

  • AutoConfigurationImportSelector实现了DeferredImportSelector,而DeferredImportSelector实现了ImportSelector接口( 该接口主要是为了导入@Configuration的配置项,而DeferredImportSelector是延期导入,当所有的@Configuration都处理过后才会执行
  • 回过头来我们看一下AutoConfigurationImportSelector的自动配备核心方法 selectImport
  •     //自动装配的方法
        public String[] selectImports(AnnotationMetadata annotationMetadata) {
            //判断是否自动装配
            if (!this.isEnabled(annotationMetadata)) {
                return NO_IMPORTS;
            } else {
                AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
                AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
                return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
            }
        }
    
        protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
            if (!this.isEnabled(annotationMetadata)) {
                return EMPTY_ENTRY;
            } else {
                //获取所有元数据信息    
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                //获取所有加载bean的条件配置
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                //过滤并删除掉重复的bean
                configurations = this.removeDuplicates(configurations);
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                this.checkExcludedClasses(configurations, exclusions);
                configurations.removeAll(exclusions);
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
            }
        }

     

  • 该方法刚开始会先判断是否进行自动装配,而后会从META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性,紧接着会调用getCandidateConfigurations方法:
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }

 

  • 在这里又遇到我们的老熟人了–SpringFactoryiesLoader, 它会读取META-INF/spring.factories下的EnableAutoConfiguration的配置,紧接着在进行排除与过滤,进而得到需要装配的类。最后让所有配置在META-INF/spring.factories下的AutoConfigurationImportListener执行AutoConfigurationImportEvent事件,代码如下:
    private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
        List<AutoConfigurationImportListener> listeners = this.getAutoConfigurationImportListeners();
        if (!listeners.isEmpty()) {
            AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
            Iterator var5 = listeners.iterator();

            while(var5.hasNext()) {
                AutoConfigurationImportListener listener = (AutoConfigurationImportListener)var5.next();
                this.invokeAwareMethods(listener);
                listener.onAutoConfigurationImportEvent(event);
            }
        }
    }

 

自动装配还是利用了SpringFactoriesLoader来加载META-INF/spring.factoires文件里所有配置的EnableAutoConfgruation,它会经过exclude和filter等操作,最终确定要装配的类.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值