首先,给出答案,SpringBoot和SpringMVC中配置类的@Impot等导入是通过Spring中的invokeBeanFactoryPostProcessors解析的

SpringBoot中的EnableAutoConfiguration是如何实现导入配置类的

在源码中咱们能够看到,配置类应该是通过AutoConfigurationImportSelector和AutoConfigurationPackages.Registrar来导入的。

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@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 {};}

AutoConfigurationPackages.Registrar是通过实现ImportBeanDefinitionRegistrar接口来实现导入的

    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.singleton(new PackageImport(metadata));        }    }

AutoConfigurationImportSelector 是通过实现ImportSelector接口实现selectImports办法来实现的。然而我比拟奇怪的是selectImports办法何时被调用,能力使得配置类被退出到IOC容器中
通过断点发现
次要进过了这么几个步骤
AbstractApplicationContext#refresh --> AbstractApplicationContext#invokeBeanFactoryPostProcessors--> PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors -->iinvokeBeanDefinitionRegistryPostProcessors#nvokeBeanDefinitionRegistryPostProcessors(这个办法中遍历了所有bean后置处理器)-->ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry-->ConfigurationClassPostProcessor#processConfigBeanDefinitions
察看到这个接口之后能够看到

    /**     * Build and validate a configuration model based on the registry of     * {@link Configuration} classes.     */    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();        String[] candidateNames = registry.getBeanDefinitionNames();        for (String beanName : candidateNames) {            BeanDefinition beanDef = registry.getBeanDefinition(beanName);            if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||                    ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {                if (logger.isDebugEnabled()) {                    logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);                }            }            else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));            }        }        // Return immediately if no @Configuration classes were found        if (configCandidates.isEmpty()) {            return;        }        // Sort by previously determined @Order value, if applicable        configCandidates.sort((bd1, bd2) -> {            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());            return Integer.compare(i1, i2);        });        // Detect any custom bean name generation strategy supplied through the enclosing application context        SingletonBeanRegistry sbr = null;        if (registry instanceof SingletonBeanRegistry) {            sbr = (SingletonBeanRegistry) registry;            if (!this.localBeanNameGeneratorSet) {                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);                if (generator != null) {                    this.componentScanBeanNameGenerator = generator;                    this.importBeanNameGenerator = generator;                }            }        }        if (this.environment == null) {            this.environment = new StandardEnvironment();        }        // Parse each @Configuration class        ConfigurationClassParser parser = new ConfigurationClassParser(                this.metadataReaderFactory, this.problemReporter, this.environment,                this.resourceLoader, this.componentScanBeanNameGenerator, registry);        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());        do {            parser.parse(candidates);//外围代码            parser.validate();            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());            configClasses.removeAll(alreadyParsed);            // Read the model and create bean definitions based on its content            if (this.reader == null) {                this.reader = new ConfigurationClassBeanDefinitionReader(                        registry, this.sourceExtractor, this.resourceLoader, this.environment,                        this.importBeanNameGenerator, parser.getImportRegistry());            }            this.reader.loadBeanDefinitions(configClasses);            alreadyParsed.addAll(configClasses);            candidates.clear();            if (registry.getBeanDefinitionCount() > candidateNames.length) {                String[] newCandidateNames = registry.getBeanDefinitionNames();                Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));                Set<String> alreadyParsedClasses = new HashSet<>();                for (ConfigurationClass configurationClass : alreadyParsed) {                    alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());                }                for (String candidateName : newCandidateNames) {                    if (!oldCandidateNames.contains(candidateName)) {                        BeanDefinition bd = registry.getBeanDefinition(candidateName);                        if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&                                !alreadyParsedClasses.contains(bd.getBeanClassName())) {                            candidates.add(new BeanDefinitionHolder(bd, candidateName));                        }                    }                }                candidateNames = newCandidateNames;            }        }        while (!candidates.isEmpty());        // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes        if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {            sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());        }        if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {            // Clear cache in externally provided MetadataReaderFactory; this is a no-op            // for a shared cache since it'll be cleared by the ApplicationContext.            ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();        }    }

通过层层代码查找之后能够找到最终实现引入的代码

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,            Collection<SourceClass> importCandidates, boolean checkForCircularImports) {        if (importCandidates.isEmpty()) {            return;        }        if (checkForCircularImports && isChainedImportOnStack(configClass)) {            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));        }        else {            this.importStack.push(configClass);            try {                for (SourceClass candidate : importCandidates) {                    if (candidate.isAssignable(ImportSelector.class)) {//引入实现了ImportSelector接口的类                        // Candidate class is an ImportSelector -> delegate to it to determine imports                        Class<?> candidateClass = candidate.loadClass();                        ImportSelector selector = BeanUtils.instantiateClass(candidateClass, ImportSelector.class);                        ParserStrategyUtils.invokeAwareMethods(                                selector, this.environment, this.resourceLoader, this.registry);                        if (selector instanceof DeferredImportSelector) {//引入实现了DeferredImportSelector接口的类                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);                        }                        else {                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);                            processImports(configClass, currentSourceClass, importSourceClasses, false);                        }                    }                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {/引入实现了ImportBeanDefinitionRegistrar接口的类                        // Candidate class is an ImportBeanDefinitionRegistrar ->                        // delegate to it to register additional bean definitions                        Class<?> candidateClass = candidate.loadClass();                        ImportBeanDefinitionRegistrar registrar =                                BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);                        ParserStrategyUtils.invokeAwareMethods(                                registrar, this.environment, this.resourceLoader, this.registry);                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());                    }                    else {                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->                        // process it as an @Configuration class                        this.importStack.registerImport(                                currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());                        processConfigurationClass(candidate.asConfigClass(configClass));                    }                }            }            catch (BeanDefinitionStoreException ex) {                throw ex;            }            catch (Throwable ex) {                throw new BeanDefinitionStoreException(                        "Failed to process import candidates for configuration class [" +                        configClass.getMetadata().getClassName() + "]", ex);            }            finally {                this.importStack.pop();            }        }    }

即SpringBoot中EnableAutoConfiguratio两种获取配置类的形式,最初均归一到这一个办法中实现了引入到IOC容器中。

欢送搜寻关注自己与敌人共同开发的微信面经小程序【大厂面试助手】和公众号【微瞰技术】