SpringBoot的主动拆卸是拆箱即用的根底,也是为服务化的前提。

一、主动拆卸的过程

1.1 @SpringBootApplication

后面一章我解说过了《SpringBoot进阶之道-@SpringBootApplication》。咱们晓得@SpringBootApplication蕴含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan。

1.2 @EnableAutoConfiguration

在上一章我解说过《SpringBoot进阶之道-@Enable模块驱动》,这种@Enabelxx的注解是开启某一项性能的注解,其原理是借助@Import,将所有合乎主动配置条件的bean定义加载到IOC容器。具体的能够去看看。

那么@EnableAutoConfiguration这个注解会开启springboot主动拆卸性能。直白的说,Spring会试图在你的classpath下找到所有配置的Bean而后进行拆卸。咱们以springboot2.x源码为例:

@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 {};    String[] excludeName() default {};}

从源码咱们得悉,要害是@Import({AutoConfigurationImportSelector.class}),借助AutoConfigurationImportSelector,@EnableAutoConfiguration能够帮忙springboot利用将所有符合条件的@Configuration配置都加载到以后SpringBoot创立并应用的ioc容器。那么我为什么这么说呢?咱们看下AutoConfigurationImportSelector源码:

public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {    ...    public AutoConfigurationImportSelector() {    }}

该类实现了DeferredImportSelector接口,而DeferredImportSelector是继承了ImportSelector:

public interface ImportSelector {    String[] selectImports(AnnotationMetadata var1);}

ImportSelector接口次要是为了导入@Configuration的配置项,而DeferredImportSelector是延期导入,当所有的@Configuration都解决过后才会执行。
咱们看看AutoConfigurationImportSelector实现的selectImports办法:

public String[] selectImports(AnnotationMetadata annotationMetadata) {        // 判断是否进行主动拆卸        if (!this.isEnabled(annotationMetadata)) {            return NO_IMPORTS;        } else {            //1加载META-INF/spring-autoconfigure-metadata.properties文件            AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());        }    }    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {        if (!this.isEnabled(annotationMetadata)) {            return EMPTY_ENTRY;        } else {            //2获取注解的属性及其值(PS:注解指的是@EnableAutoConfiguration注解)            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);            //3.在classpath下所有的META-INF/spring.factories文件中查找org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,并将其封装到一个List中返回            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);            //4.对上一步返回的List中的元素去重、排序            configurations = this.removeDuplicates(configurations);            //5.根据第2步中获取的属性值排除一些特定的类            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);            //6.对上一步中所失去的List进行过滤,过滤的根据是条件匹配。这里用到的过滤器是            //org.springframework.boot.autoconfigure.condition.OnClassCondition最终返回的是一个ConditionOutcome[]数组。            //(PS:很多类都是依赖于其它的类的,当有某个类时才会拆卸,所以这次过滤的就是依据是否有某个            //class进而决定是否拆卸的。这些类所依赖的类都写在META-INF/spring-autoconfigure-metadata.properties文件里)            this.checkExcludedClasses(configurations, exclusions);            configurations.removeAll(exclusions);            configurations = this.filter(configurations, autoConfigurationMetadata);            this.fireAutoConfigurationImportEvents(configurations, exclusions);            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);        }    }     ....    public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {        return loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");    }}

从下面的源码得悉,该办法先判断是否进行主动拆卸,而后从META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相干属性,而后调用getCandidateConfigurations办法:

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

这个时候咱们看到个Spring框架原有的一个工具类SpringFactoriesLoader,其次要的工作是从指定的META-INF/spring.factories加载配置,即依据@EnableAutoConfiguration的残缺类名"org.springframework.boot.autoconfigure.EnableAutoConfiguration"作为查找的Key,获取对应的配置,通过反射失去对应的一组@Configuration类。spring.factories中EnableAutoConfiguration如下:

# Auto Configureorg.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,\....

总结:主动拆卸就是利用SpringFactoriesLoader从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置项通过反射实例化为标注了@Configuration的JavaConfig模式的配置类,而后汇总并加载到ioc容器。所以,以前咱们须要本人配置的货色,主动配置类都帮咱们实现了,是不是很嗨~~~