目录
三、@Import(AutoConfigurationImportSelector.class)
1)、AutoConfigurationImportSelector介绍
2-1)、ConfigurationClassParser#parse()
2-2)、this.deferredImportSelectorHandler.process()
2-2-2)、第二步:processGroupImports()
本篇源码基于spring-boot-2.1.0.RELEASE版本进行分析,各个版本可能存在一些差别。
一、简介
SpringBoot的启动从main()方法开始:
在主启动类上,我们只需要加上@SpringBootApplication注解,就能成功启动springboot应用了,那么我们就从注解入手,看下它是如何帮我们配置好所需要的一些环境的。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// @SpringBootConfiguration内部使用@Configuration修饰,标记启动类是一个Spring的配置类
@SpringBootConfiguration
// @EnableAutoConfiguration: 实现自动装配的核心注解. 内部包含两个注解:@AutoConfigurationPackage + @Import(AutoConfigurationImportSelector.class)
@EnableAutoConfiguration
// 包扫描:扫描启动类所在的包以及子包所有Bean组件并注册到IOC容器中
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
// SpringBoot项目启动的核心注解
// @SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan
public @interface SpringBootApplication {
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
// 等同于EnableAutoConfiguration注解的exclude属性
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
// 等同于EnableAutoConfiguration注解的excludeName属性
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
/**
* Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
* for a type-safe alternative to String-based package names.
* @return base packages to scan
* @since 1.3.0
*/
// 等同于ComponentScan注解的basePackages属性
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
* scan for annotated components. The package of each class specified will be scanned.
* <p>
* Consider creating a special no-op marker class or interface in each package that
* serves no purpose other than being referenced by this attribute.
* @return base packages to scan
* @since 1.3.0
*/
// 等同于ComponentScan注解的basePackageClasses属性
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
@SpringBootApplication 使用三个注解修饰:
1)、@SpringBootConfiguration
标记启动类是一个Spring的配置类。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
// 相当于@SpringBootConfiguration就是@Configuration
public @interface SpringBootConfiguration {
}
2)、@ComponentScan
扫描启动类所在的包以及子包所有Bean组件并注册到IOC容器中。
3)、@EnableAutoConfiguration
实现自动装配的核心注解,内部包含两个注解:@AutoConfigurationPackage + @Import(AutoConfigurationImportSelector.class)。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 自动配置包
@AutoConfigurationPackage
// 使用@Import注解导入AutoConfigurationImportSelector类,实现了ImportSelector接口,重写了selectImports()方法,帮助我们返回所有需要被注册为bean的类全限定类名的数组集合
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* 排除特定的自动配置类,使它们永远不会被应用
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* 排除特定的自动配置类名称,使其永远不会被应用
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
springboot的自动装配就是依靠@EnableAutoConfiguration这个注解实现的,而@EnableAutoConfiguration又是由下面两部分组成:
1、@AutoConfigurationPackage
2、@Import(AutoConfigurationImportSelector.class)
二、@AutoConfigurationPackage
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
// 向容器中导入了AutoConfigurationPackages.Registrar组件
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
可以看到,@AutoConfigurationPackage注解的功能是由@Import注解实现的,它是Spring框架的底层注解,它的作用就是给容器中导入某个组件类AutoConfigurationPackages.Registrar,我们看下这是个什么组件?
@AutoConfigurationPackage注解的作用是将添加该注解的类所在的package作为自动配置package进行管理。也就是说当SpringBoot应用启动时默认会将启动类所在的package作为自动配置的package,这样主程序类所在包及所有子包下的组件就会被扫描到spring容器中。
// 实现了ImportBeanDefinitionRegistrar、DeterminableImports接口,重写了registerBeanDefinitions()、determineImports()方法
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
// 注册bean定义
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
// 返回一组需要注入的对象
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {