SpringBoot自动装配流程

1.启动类上面有一个@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}
)}
)

主要涉及以下几个注解: 

@SpringBootConfiguration

作用:标记这个类是一个Springboot的配置类。

@ComponentScan

作用:自动扫描包(扫描当前主启动类同级的包)并加载符合条件的组件或者bean,将这个bean定义加载到IOC容器中。

@EnableAutoConfiguration

作用:开启自动配置功能

2.点击@EnableAutoConfiguration,进入到这个注解里面,有以下几个注解。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
主要涉及以下几个注解:
@AutoConfigurationPackage

作用:自动注册包

@Import({AutoConfigurationImportSelector.class})

作用: 给容器导入组件

AutoConfigurationImportSelector.class

作用:自动配置导入选择器

3.点击AutoConfigurationImportSelector进入查看源码

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

 selectImports()是AutoConfigurationImportSelector的核心函数,其核心功能就是获取spring.factories中EnableAutoConfiguration所对应的Configuration类列表。

  AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
看到selectImports方法里的这一行,我们点击继续查看进入到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);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }
此方法中有一个 this.getCandidateConfigurations(annotationMetadata, attributes); 获得候选配置的方法;点击这个方法进入到getCandidateConfiguration()这个方法。
 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;
    }
点击getSpringFactoriesLoaderFactoryClass()方法,这个方法,标注了EnableAutoConfiguration注解的类。
 protected Class<?> getSpringFactoriesLoaderFactoryClass() {
        return EnableAutoConfiguration.class;
    }

getCandidateConfiguration()方法又调用SpringFactoriesLoader 类的静态方法!我们进入SpringFactoriesLoader类loadFactoryNames() 方法------->获取所有的加载配置。

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
    }
loadFactoryNames()方法看到这一行
  return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
我们继续点击查看 loadSpringFactories 方法
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();

                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        String factoryTypeName = ((String)entry.getKey()).trim();
                        String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                        int var10 = var9.length;

                        for(int var11 = 0; var11 < var10; ++var11) {
                            String factoryImplementationName = var9[var11];
                            result.add(factoryTypeName, factoryImplementationName.trim());
                        }
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var13) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
            }
        }
    }

loadSpringFactories 方法中的classLoader.getResources(“META-INF/spring.factories”) —》获取项目资源;

ClassLoader.getSystemResources(“META-INF/spring.factories”)—》获取系统资源。

项目资源和系统资源都是在"META-INF/spring.factories"文件中获取的。

总结

1.SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值。

2.将这些值作为自动配置类导入容器,自动配置类就会生效,帮助我们进行自动配置工作。

3.整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;

4.它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration),就是给容器中导入这个场景需要的所有组件,并配置好这些组件。

5.有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作。

猜你喜欢

转载自blog.csdn.net/weixin_50519232/article/details/126753338
今日推荐