0
点赞
收藏
分享

微信扫一扫

【SpringBoot】自动装配实现原理

探头的新芽 2022-04-14 阅读 76

SpringBoot自动装配实现原理

首先我们要知道Spring Boot自动装配的核心注解是@SpringBootApplication,该注解是spring boot的启动类注解,它是一个复合注解,里面包含
1.@SpringBootConfiguration:

该注解上有一个 @Configuration注解,表示这个spring boot启动类是一个配置类,最终要被注入到spring容器中。

2.@EnableAutoConfiguration

表示开启自动配置,它也是一个复合注解,里面包含
a:@AutoConfigurationPackage:该注解上有一个@Import(AutoConfigurationPackages.Registrar.class)注解,
	其中 Registrar 类的作用是将启动类所在包下的所有子包的组件扫描注入到spring容器中。
b:@Import(AutoConfigurationImportSelector.class):其中AutoConfigurationImportSelector类中有一个getCandidateConfigurations()方法,
	该方法通过SpringFactoriesLoader.loadFactoryNames()方法查找位于META-INF/spring.factories文件中的所有自动配置类,并加载这些类。

所以spring boot在整个的启动过程中,其实就是在类路径的META-INF/spring.factories 文件中找到EnableAutoConfiguration对应的所有的自动配置类,然后将所有自动配置类加载到spring容器中。
我们来看一下流程图
springboot自动装配实现原理流程图
下面我们附上源码
1.@SpringBootApplication中的@EnableAutoConfiguration表示开启自动装配
2.@Import({AutoConfigurationImportSelector.class}) 该注解表示导入该 AutoConfigurationImportSelector类
3.AutoConfigurationImportSelector类下会有一个AutoConfigurationGroup内部类
该内部类下的process方法会先被执行

public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
   Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
         () -> String.format("Only %s implementations are supported, got %s",
               AutoConfigurationImportSelector.class.getSimpleName(),
               deferredImportSelector.getClass().getName()));
   AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
         .getAutoConfigurationEntry(annotationMetadata);
         //保存到autoConfigurationEntries 这个list中
   this.autoConfigurationEntries.add(autoConfigurationEntry);
   //把配置类包装成一个map返回
   for (String importClassName : autoConfigurationEntry.getConfigurations()) {
      this.entries.putIfAbsent(importClassName, annotationMetadata);
   }
}

4.然后调用getAutoConfigurationEntry方法

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    if (!this.isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    } else {
        AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        configurations = this.removeDuplicates(configurations);
        Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
        this.checkExcludedClasses(configurations, exclusions);
        //删除需要排除的类
        configurations.removeAll(exclusions);
        configurations = this.getConfigurationClassFilter().filter(configurations);
        this.fireAutoConfigurationImportEvents(configurations, exclusions);
        //包装成AutoConfigurationEntry类
         return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    }
}

5.这个方法会获取SpringBootApplication中的exclude、excludeName排除的类

protected AnnotationAttributes getAttributes(AnnotationMetadata metadata) {
    String name = this.getAnnotationClass().getName();
    AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(name, true));
    Assert.notNull(attributes, () -> {
        return "No auto-configuration attributes found. Is " + metadata.getClassName() + " annotated with " + ClassUtils.getShortName(name) + "?";
    });
    return attributes;
}

6.通过spi机制 获取META-INFO下的spring.factoryies中@EnableAutoConfiguration注解
为key的value值,总共有129个

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

7.删除重复的

protected final <T> List<T> removeDuplicates(List<T> list) {
    return new ArrayList(new LinkedHashSet(list));
}

8.获取到需要排除的类

protected Set<String> getExclusions(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    Set<String> excluded = new LinkedHashSet();
    excluded.addAll(this.asList(attributes, "exclude"));
    excluded.addAll(Arrays.asList(attributes.getStringArray("excludeName")));
    excluded.addAll(this.getExcludeAutoConfigurationsProperty());
    return excluded;
}

9.保存到autoConfigurationEntries 这个list中
10.把配置类包装成一个map返回

注:9、10请参照第3步中的源码

举报

相关推荐

0 条评论