SpringBoot自动装配原理 - 图1

    自动装配是SpringBoot中通过@EnableAutoCinfiguration注解来开启的,这个注解的声明在启动类注解@SpringBootApplication内;

    SpringBoot自动装配原理 - 图2
    注:
    @Enable注解:在Spring3.1就已经支持该类型注解,主要作用是吧相关组件的Bean装配到IOC容器中;@Enable注解是对JavaConfig的进一步完善,为使用S任凭Framework的开发者减少了配置代码量,降低了使用难度;如果基于JavaConfig的形式来完成Bean的加载,则必须使用@Configuration注解及Bean注解;而@Enable本质上就是对着两个注解的封装;

    @EnableAutoConfiguration
    进入该注解可以看到除了@Import为还有一个@AutoConfigurationPackage(使用了改注解的累下的包及子包扫描到IOC容器中),而可以看见Import中引入了一个AutoConfigurationImportSelector,该AutoConfigurationImportSelector实现了ImportSelector,他只有一个selectImports抽象方法,并返回一个String数组,在这个shuzh中可以指定需要装配到IOC容器的类;

    1. public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
    2. private static final AutoConfigurationImportSelector.AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationImportSelector.AutoConfigurationEntry();
    3. private static final String[] NO_IMPORTS = new String[0];
    4. private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);
    5. private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
    6. private ConfigurableListableBeanFactory beanFactory;
    7. private Environment environment;
    8. private ClassLoader beanClassLoader;
    9. private ResourceLoader resourceLoader;
    10. public AutoConfigurationImportSelector() {
    11. }
    12. public String[] selectImports(AnnotationMetadata annotationMetadata) {
    13. if (!this.isEnabled(annotationMetadata)) {
    14. return NO_IMPORTS;
    15. } else {
    16. AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
    17. AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
    18. return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    19. }
    20. }
    21. ......................
    22. }

    在selectImports方法中,这个方法主要有两个功能1.AutoConfigurationMetadataLoader.loadMetadata从META-INF/Spring-autoconfigure-metadata.properties中加载自动装配的条件元数据2.收集所有符合条件的配置类AutoConfigurationEntry.getConfigurations(),完成自动装配需要注意的是在AutoConfigurationImportSelector中不执行selectImports()方法,而是通过ConfigurationClassPostProcessor中的processConfigBeanDefinitions方法来扫描和注册所有配置类的Bean,最终还是会调用getAutoConfigurationEntry方法获得所有需要自动装配的类;在getAutoConfigurationEntry方法中通过去重等操作,得到最终需要实现自动装配的类;而得到的核心方法是getCandidateConfigurations

    1. protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
    2. if (!this.isEnabled(annotationMetadata)) {
    3. return EMPTY_ENTRY;
    4. } else {
    5. AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
    6. List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
    7. configurations = this.removeDuplicates(configurations);
    8. Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
    9. this.checkExcludedClasses(configurations, exclusions);
    10. configurations.removeAll(exclusions);
    11. configurations = this.filter(configurations, autoConfigurationMetadata);
    12. this.fireAutoConfigurationImportEvents(configurations, exclusions);
    13. return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
    14. }
    15. }

    在该方法中

    1. protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    2. List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
    3. 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.");
    4. return configurations;
    5. }

    使用了SpringFactoriesLoader,它会扫描classPath下的META-INF/Spring.factories文件;根据配置文件中的key得到value值