ok,本博客尝试跟一下Springboot的自动配置源码,做一下笔记记录,自动配置是Springboot的一个很关键的特性,也容易被忽略的属性,因为这个属性被包括在@SpringBootApplication注解里,所以不去跟一下源码都不知道还有这个属性,ps:本博客源码基于SpringBoot1.5.7版本
@SpringBootApplicationok,跟一下@SpringBootApplication,发现@SpringBootApplication其实是一个复合的注解,由很多注解构成,@EnableAutoConfiguration其实只是其一部分,@EnableAutoConfiguration就是开启自动配置的注解
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.context.TypeExcludeFilter; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.core.annotation.AliasFor; @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 { .... Class<?>[] scanBasePackageClasses() default {}; } @EnableAutoConfiguration点进@EnableAutoConfiguration,比较重要的列出来:
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; } @AutoConfigurationPackage先看@AutoConfigurationPackage源码,这个注解是开启自动配置包的,关注点在@Import({Registrar.class}),核心在Registrar类
备注:@import注解是Spring的底层注解,作用是导入一个组件到容器里
package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar; import org.springframework.context.annotation.Import; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({Registrar.class}) public @interface AutoConfigurationPackage { }Registrar 类是AutoConfigurationPackages类的静态内部类,
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar() { } public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()); } public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata)); } }看一下(new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()获取的是什么,用idea的工具,计算表达式,可以看到其实获取的是SpringBoot启动类上面的包名
AnnotationMetadata:SpringBoot注解元数据
所以,@AutoConfigurationPackage开启后,就可以将主配置类(@SpringBootApplication)所在包及其子包里面的所有组件都扫描到Spring容器里
public static void register(BeanDefinitionRegistry registry, String... packageNames) { if (registry.containsBeanDefinition(BEAN)) { BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN); ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues(); constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames)); } else {// Spring容器里没有找到对应组件 /* 将组件注册到Spring容器里 */ GenericBeanDefinition beanDefinition = new GenericBeanDefinition(); beanDefinition.setBeanClass(AutoConfigurationPackages.BasePackages.class); beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames); beanDefinition.setRole(2); registry.registerBeanDefinition(BEAN, beanDefinition); } }