SpringBoot自动配置

2020-09-23  本文已影响0人  有梦想的虫子_2018

1、@SpringBootApplication注解

springboot启动类上都会配置@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 {
    ……
}

2、@EnableAutoConfiguration注解

我们可以看到@SpringBootApplication是组合注解,其中@EnableAutoConfiguration注解进行自动配置,加载bean到IOC容器。

@EnableAutoConfiguration

@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 {};//排除指定class
    String[] excludeName() default {};//排除指定类名

}

@EnableAutoConfiguration由两个关键注解组成@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class),下面我们分别解释下这两个注解。

3、@AutoConfigurationPackage注解

/**
 * Registers packages with {@link AutoConfigurationPackages}.
 *  When no {@link #basePackages  base packages} or {@link #basePackageClasses base package classes} are specified, the
 * package of the annotated class is registered.
* 注册在basePackages和basePackageClasses指定的class,如果没有指定那么注册
* 这个注解类修饰的类所在的包
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};
    Class<?>[] basePackageClasses() default {};
}

@Import(AutoConfigurationPackages.Registrar.class)

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

        @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
        }

        @Override
        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new PackageImports(metadata));
        }

    }

把启动类所在的包注册进去了


image.png

4、@Import(AutoConfigurationImportSelector.class)

自动装配的核心是扫描约定目录下的文件进行解析,解析完成之后把得到的Configuration配置类通过ImportSelector进行导入,从而完成Bean的自动装配过程。springboot由AutoConfigurationImportSelector来实现的。下面进行详细解析:


image.png

selectImports方法

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

最终调用到getAutoConfigurationEntry方法获取所有需要自动装配的配置类。

protected AutoConfigurationEntry getAutoConfigurationEntry(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 = getConfigurationClassFilter().filter(configurations);
        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;
    }

这里用到了SpringFactoriesLoader,它是Spring内部提供的一种约定俗成的加载方式,类似于Java中SPI(Service Provider Interface)。简单来说,它会扫描META-INF/spring.factories问价,spring.factories问价中的数据以key=value形式存储。在这个场景中,Key对应EnableAutoConfiguration,Value是多个配置类,也就是getCandidateConfigurations方法返回的值。

image.png

org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration

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.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\

5、总结

Spring Cloud Alibaba 微服务原理与实战 ——谭锋(Mic)著

上一篇 下一篇

猜你喜欢

热点阅读