SpringBoot自动装配

Posted chauncyl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot自动装配相关的知识,希望对你有一定的参考价值。

前言:我们知道如果想将我们自己写的类注入IOC容器中只需要打上基础的@Component注解或者是@Configuration注解,但是SpringBoot是怎么加载我们在maven中导入的第三方SDK呢?

一般导入第三方库需要两个步骤:

  1. 下载第三方SDK(直接下载,maven,npm,pip)
  2. 导入(import)

SpringBoot的自动配置原理与上述稍稍不同:

1.首先从SpringBoot入口文件@SpringBootApplication讲起,这个注解内部又包装了三个重要的注解,正是这三个注解实现了SpringBoot自动装配功能。

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

2.@SpringBootConfiguration:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration{

这个注解基础就是一个基础@Component注解,将bean注入到IOC容器中。

3.@EnableAutoConfiguration:内部通过反射导入了自动装配选择器

@Import(AutoConfigurationImportSelector.class)

AutoConfigurationImportSelector:

@Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        }
        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
                .loadMetadata(this.beanClassLoader);
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
                annotationMetadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }


protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
            AnnotationMetadata annotationMetadata) {
        if (!isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        }
        AnnotationAttributes attributes = getAttributes(annotationMetadata);
        List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
        configurations = removeDuplicates(configurations);
        Set<String> exclusions = getExclusions(annotationMetadata, attributes);
        checkExcludedClasses(configurations, exclusions);
        configurations.removeAll(exclusions);
        configurations = filter(configurations, autoConfigurationMetadata);
        fireAutoConfigurationImportEvents(configurations, exclusions);
        return new AutoConfigurationEntry(configurations, exclusions);
    }


protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
                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;
    }

这个选择器最终返回一个string对象,即为需要装配的配置类名。如何获取的呢?这里只贴出部分关键代码:首先selectImports函数中调用getAutoConfigurationEntry,getAutoConfigurationEntry调用getCandidateConfigurations(关键),这个函数中调用SpringFactoriesLoader.loadFactoryNames加载了spring-boot-autoconfigure中的spring.factories文件。而spring.factories中的键值对就是要装配的配置类名,在maven中引入后springboot便将配置类名添加到spring.factories中了。

spring.factories:

#Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,

4.@ComponentScan:该注解将自动将和SpringBoot入口文件同级的包扫描,寻找bean。定义Spring Beans的第一步是使用正确的注解@Component或@Service或@Repository。但是,Spring不知道你定义了某个bean除非它知道从哪里可以找到这个bean。作用:配合@Component一起食用将自己写的bean注册到IOC中。

为什么springboot这么麻烦?

因为springboot不仅仅时简单的导入类,而是将类加载到注册到IOC中。

以上是关于SpringBoot自动装配的主要内容,如果未能解决你的问题,请参考以下文章

深入理解SpringBoot之自动装配

SpringBoot自动装配原理详细讲解(清楚 明白)

SpringBoot自动装配原理详细讲解(清楚 明白)

SpringBoot的自动装配(一)

跟跟Springboot启动容器,自动装配的过程

如何自动装配在 SpringBoot 应用程序中具有带参数的构造函数的组件