什么是自动装配

简介: 什么是自动装配

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情

什么是自动装配

在使用SpringBoot的时候,会自动将Bean装配到IoC容器中,自动装配大致过程如下:

  • 获取到组件META-INF文件夹下的spring.factories文件
  • spring.factories文件中列出需要注入IoC容器的类
  • 将实体类注入到IoC容器中进行使用

自动装配原理

通过SpringBoot启动类 来分析整个过程,首先看下启动类的代码:

@SpringBootApplication
public class CompanyProjectApplication {
      public static void main(String[] args) {
        SpringApplication.run(RuoYiApplication.class, args);
    }

@SpringBootApplication

可以看到最主要部分就是@SpringBootApplication注解,进入注解类,我们能够发现@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 {
    ...
}

@Target({ElementType.TYPE}) // 表明 修饰的注解的位置 TYPE 表示只能修饰类

@Retention(RetentionPolicy.RUNTIME) // 表明注解的作用域

@Documented // API 文档抽取的时候会将该注解 抽取到API文档中

@Inherited // 表示注解的继承

@SpringBootConfiguration这个注解的本质其实是@Configuration注解。

@ComponentScan注解,该注解的作用是用来指定扫描路径的,如果不指定特定的扫描路径的话,扫描的路径是当前修饰的类所在的包及其子包。

那么就剩@EnableAutoConfiguration,这个注解就是SpringBoot自动装配的关键。

@EnableAutoConfiguration

进入@EnableAutoConfiguration注解,可以看到@AutoConfigurationPackage和@Import({AutoConfigurationImportSelector.class})

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

通过@AutoConfigurationPackage注解将添加该注解的类所在的package作为自动配置package进行管理。

而@EnableAutoConfiguration注解最重要的是AutoConfigurationImportSelector.class,将需要装配的类装配到IoC容器中,下面重点分析一下这个类的实现

    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;
    }

进入到AutoConfigurationImportSelector 类,根据断点debug,进入getAutoConfigurationEntry方法,调用到了方法getCandidateConfigurations,调用到了 SpringFactoriesLoader的loadFactoryNames,通过debug可以看到加载到了META-INF/spring.factories文件

configurations = this.filter(configurations, autoConfigurationMetadata);调用下面方法

    private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
        long startTime = System.nanoTime();
        String[] candidates = StringUtils.toStringArray(configurations);
        boolean[] skip = new boolean[candidates.length];
        boolean skipped = false;
        Iterator var8 = this.getAutoConfigurationImportFilters().iterator();

        while(var8.hasNext()) {
            AutoConfigurationImportFilter filter = (AutoConfigurationImportFilter)var8.next();
            this.invokeAwareMethods(filter);
            boolean[] match = filter.match(candidates, autoConfigurationMetadata);

            for(int i = 0; i < match.length; ++i) {
                if (!match[i]) {
                    skip[i] = true;
                    candidates[i] = null;
                    skipped = true;
                }
            }
        }

        if (!skipped) {
            return configurations;
        } else {
            List<String> result = new ArrayList(candidates.length);

            int numberFiltered;
            for(numberFiltered = 0; numberFiltered < candidates.length; ++numberFiltered) {
                if (!skip[numberFiltered]) {
                    result.add(candidates[numberFiltered]);
                }
            }

            if (logger.isTraceEnabled()) {
                numberFiltered = configurations.size() - result.size();
                logger.trace("Filtered " + numberFiltered + " auto configuration class in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
            }

            return new ArrayList(result);
        }
    }

可以看到匹配方法 match。 autoConfigurationMetadata,的本质是 加载的 META-INF/spring-autoconfigure-metadata.properties 的文件中的内容。过滤之后仅剩46个文件

到这其实我们就已经给大家介绍完了SpringBoot的自动装配原理。在网上找到了一张总结好的流程图如下:

img

~好了,本文就给大家介绍到这里,感觉有帮助的,留下个赞或评论再走吧!谢啦~ 💐

相关文章
|
XML 数据格式 容器
基于注解的自动装配~
基于注解的自动装配~
|
XML Java 数据格式
spring中bean的自动装配(详细)
spring中bean的自动装配(详细)
859 0
|
Java Spring 容器
深入理解Spring源码之自动装配
深入理解Spring源码之自动装配
64 0
|
容器
05 依赖注入-自动装配
用于引用类型的依赖注入
82 0
|
XML Java 测试技术
Bean的自动装配
- 自动装配Spring满足bean依赖一种方式! - Spring会在上下文中自动寻找,并自动给Bean装配属性
|
XML 开发框架 Java
Spring | Bean自动装配详解
Bean自动装配详解
610 0
Spring | Bean自动装配详解
|
Java Spring
Spring Bean自动装配
1.通过ID自动装配 Spring Bean自动装配可以自动搜索beans.xml中的bean,进行自动装配,这样就可以使开发人员不必显示的声明它 例如,Person.java中包含了猫和狗的实体类对象
121 0
|
Java Spring
Spring基于注解方式实现属性注入(超详细)
Spring基于注解方式实现属性注入(超详细)
Spring基于注解方式实现属性注入(超详细)
|
XML Java 数据格式
springBeans 的自动装配
Beans 自动装配 Spring 容器可以在不使用 和 元素的情况下自动装配相互协作的 bean 之间的关系。
|
Java Spring
Spring框架学习(四) 自动装配
Spring框架学习(四) 自动装配
131 0
下一篇
DataWorks