面试官:知道 springboot 的启动原理吗?( 三 )


@AutoConfigurationPackage 注解这个注解主要是通过 @Import 注解导入了 AutoConfigurationPackages.Registrar.class 类 。
实现如下:
/** * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing * configuration. * @author 老马啸西风 */@Order(Ordered.HIGHEST_PRECEDENCE)static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {    @Override    public void registerBeanDefinitions(AnnotationMetadata metadata,            BeanDefinitionRegistry registry) {        register(registry, new PackageImport(metadata).getPackageName());    }    @Override    public Set<Object> determineImports(AnnotationMetadata metadata) {        return Collections.<Object>singleton(new PackageImport(metadata));    }}它其实是注册了一个Bean的定义 。
new PackageImport(metadata).getPackageName(),它其实返回了当前主程序类的同级以及子级的包组件 。
@Import(EnableAutoConfigurationImportSelector.class)我们来看一下另外一个注解,@Import(EnableAutoConfigurationImportSelector.class) 。
EnableAutoConfigurationImportSelector 实现如下:
public class EnableAutoConfigurationImportSelector        extends AutoConfigurationImportSelector {    @Override    protected boolean isEnabled(AnnotationMetadata metadata) {        if (getClass().equals(EnableAutoConfigurationImportSelector.class)) {            return getEnvironment().getProperty(                    EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class,                    true);        }        return true;    }}这个方法一眼看上去也是平平无奇,因为核心实现都在父类中 。
最核心的方法如下:
@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {    // 不启用,直接返回无导入    if (!isEnabled(annotationMetadata)) {        return NO_IMPORTS;    }    try {        AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader                .loadMetadata(this.beanClassLoader);        AnnotationAttributes attributes = getAttributes(annotationMetadata);        // 这一行回去加载 springboot 指定的文件        List<String> configurations = getCandidateConfigurations(annotationMetadata,                attributes);        configurations = removeDuplicates(configurations);        configurations = sort(configurations, autoConfigurationMetadata);        Set<String> exclusions = getExclusions(annotationMetadata, attributes);        checkExcludedClasses(configurations, exclusions);        configurations.removeAll(exclusions);        configurations = filter(configurations, autoConfigurationMetadata);        fireAutoConfigurationImportEvents(configurations, exclusions);        return configurations.toArray(new String[configurations.size()]);    }    catch (IOException ex) {        throw new IllegalStateException(ex);    }}我们用过的各种 springboot-starter,使用起来引入一个 jar 就可以使用了 。


推荐阅读