谈起SpringBoot,面试官必问:讲述一下 SpringBoot 自动装配原理?

SpringBoot自动配置原理是什么?

面试过程中问得最多的可能是自动装配的原理,而自动装配是在启动过程中完成,只不过在刚开始的时候我们选择性的跳过了,下面详细讲解自动装配的过程。

1、在springboot的启动过程中,有一个步骤是创建上下文,如果不记得可以看下面的代码:

public ConfigurableApplicationContext run(String... args) {        StopWatch stopWatch =newStopWatch();        stopWatch.start();        ConfigurableApplicationContext context =null;        Collection exceptionReporters =newArrayList<>();        configureHeadlessProperty();        SpringApplicationRunListeners listeners = getRunListeners(args);        listeners.starting();try{            ApplicationArguments applicationArguments =newDefaultApplicationArguments(args);            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);            configureIgnoreBeanInfo(environment);            Banner printedBanner = printBanner(environment);            context = createApplicationContext();            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,newClass[] { ConfigurableApplicationContext.class},context);//此处完成自动装配的过程            prepareContext(context, environment, listeners, applicationArguments, printedBanner);            refreshContext(context);            afterRefresh(context, applicationArguments);            stopWatch.stop();if(this.logStartupInfo) {newStartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);            }            listeners.started(context);            callRunners(context, applicationArguments);        }catch(Throwable ex) {            handleRunFailure(context, ex, exceptionReporters, listeners);thrownewIllegalStateException(ex);        }try{            listeners.running(context);        }catch(Throwable ex) {            handleRunFailure(context, ex, exceptionReporters,null);thrownewIllegalStateException(ex);        }returncontext;    }

2、在prepareContext方法中查找load方法,一层一层向内点击,找到最终的load方法

//prepareContext方法privatevoid prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,            SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {        context.setEnvironment(environment);        postProcessApplicationContext(context);        applyInitializers(context);        listeners.contextPrepared(context);if(this.logStartupInfo) {            logStartupInfo(context.getParent() ==null);            logStartupProfileInfo(context);        }// Add boot specific singleton beansConfigurableListableBeanFactory beanFactory = context.getBeanFactory();        beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if(printedBanner !=null) {            beanFactory.registerSingleton("springBootBanner", printedBanner);        }if(beanFactory instanceof DefaultListableBeanFactory) {            ((DefaultListableBeanFactory) beanFactory)                    .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);        }if(this.lazyInitialization) {            context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());        }// Load the sourcesSet sources = getAllSources();        Assert.notEmpty(sources,"Sources must not be empty");//load方法完成该功能load(context, sources.toArray(new Object[0]));        listeners.contextLoaded(context);    }/**    * Load beans into the application context.    *@paramcontext the context to load beans into    *@paramsources the sources to load    * 加载bean对象到context中    */protectedvoid load(ApplicationContext context, Object[] sources) {if(logger.isDebugEnabled()) {            logger.debug("Loading source "+ StringUtils.arrayToCommaDelimitedString(sources));        }//获取bean对象定义的加载器BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);if(this.beanNameGenerator !=null) {            loader.setBeanNameGenerator(this.beanNameGenerator);        }if(this.resourceLoader !=null) {            loader.setResourceLoader(this.resourceLoader);        }if(this.environment !=null) {            loader.setEnvironment(this.environment);        }        loader.load();    }/**    * Load the sources into the reader.    *@returnthe number of loaded beans    */int load() {        int count =0;for(Object source :this.sources) {            count += load(source);        }returncount;    }

3、实际执行load的是BeanDefinitionLoader中的load方法,如下:

//实际记载bean的方法privateintload(Object source){        Assert.notNull(source,"Source must not be null");//如果是class类型,启用注解类型if(sourceinstanceofClass) {returnload((Class) source);        }//如果是resource类型,启动xml解析if(sourceinstanceofResource) {returnload((Resource) source);        }//如果是package类型,启用扫描包,例如@ComponentScanif(sourceinstanceofPackage) {returnload((Package) source);        }//如果是字符串类型,直接加载if(sourceinstanceofCharSequence) {returnload((CharSequence) source);        }thrownewIllegalArgumentException("Invalid source type "+ source.getClass());    }

4、下面方法将用来判断是否资源的类型,是使用groovy加载还是使用注解的方式

privateint load(Class source) {//判断使用groovy脚本if(isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {// Any GroovyLoaders added in beans{} DSL can contribute beans hereGroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);load(loader);        }//使用注解加载if(isComponent(source)) {this.annotatedReader.register(source);return1;        }return0;    }

5、下面方法判断启动类中是否包含@Component注解,但是会神奇的发现我们的启动类中并没有该注解,继续更进发现MergedAnnotations类传入了一个参数

SearchStrategy.TYPE_HIERARCHY,会查找继承关系中是否包含这个注解,@SpringBootApplication-->@SpringBootConfiguration-->@Configuration-->@Component,当找到@Component注解之后,会把该对象注册到AnnotatedBeanDefinitionReader对象中

privatebooleanisComponent(Classtype) {// This has to be a bit of a guess. The only way to be sure that this type is// eligible is to make a bean definition out of it and try to instantiate it.if(MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY).isPresent(Component.class)) {returntrue;  }// Nested anonymous classes are not eligible for registration, nor are groovy// closuresreturn!type.getName().matches(".*\\$_.*closure.*") && !type.isAnonymousClass()        &&type.getConstructors() !=null&&type.getConstructors().length !=0;}/**

    * Register a bean from the given bean class, deriving its metadata from

    * class-declared annotations.

    * 从给定的bean class中注册一个bean对象,从注解中找到相关的元数据

    */privatevoiddoRegisterBean(Class beanClass,@NullableStringname,@NullableClass[] qualifiers,@NullableSupplier supplier,@NullableBeanDefinitionCustomizer[] customizers) {        AnnotatedGenericBeanDefinition abd =newAnnotatedGenericBeanDefinition(beanClass);if(this.conditionEvaluator.shouldSkip(abd.getMetadata())) {return;        }        abd.setInstanceSupplier(supplier);        ScopeMetadata scopeMetadata =this.scopeMetadataResolver.resolveScopeMetadata(abd);        abd.setScope(scopeMetadata.getScopeName());StringbeanName = (name !=null? name :this.beanNameGenerator.generateBeanName(abd,this.registry));        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);if(qualifiers !=null) {for(Class qualifier : qualifiers) {if(Primary.class == qualifier) {                    abd.setPrimary(true);                }elseif(Lazy.class == qualifier) {                    abd.setLazyInit(true);                }else{                    abd.addQualifier(newAutowireCandidateQualifier(qualifier));                }            }        }if(customizers !=null) {for(BeanDefinitionCustomizer customizer : customizers) {                customizer.customize(abd);            }        }        BeanDefinitionHolder definitionHolder =newBeanDefinitionHolder(abd, beanName);        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder,this.registry);        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder,this.registry);    }/**

    * Register the given bean definition with the given bean factory.

    * 注册主类,如果有别名可以设置别名

    */publicstaticvoidregisterBeanDefinition(            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)            throws BeanDefinitionStoreException {// Register bean definition under primary name.StringbeanName = definitionHolder.getBeanName();        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());// Register aliases for bean name, if any.String[] aliases = definitionHolder.getAliases();if(aliases !=null) {for(Stringalias : aliases) {                registry.registerAlias(beanName, alias);            }        }    }//@SpringBootApplication@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@interfaceSpringBootApplication {}//@SpringBootConfiguration@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configurationpublic@interfaceSpringBootConfiguration {}//@Configuration@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic@interfaceConfiguration {}

当看完上述代码之后,只是完成了启动对象的注入,自动装配还没有开始,下面开始进入到自动装配。

6、自动装配入口,从刷新容器开始

@Overridepublicvoidrefresh()throwsBeansException, IllegalStateException{synchronized(this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try{// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.// 此处是自动装配的入口invokeBeanFactoryPostProcessors(beanFactory);            }

7、在

invokeBeanFactoryPostProcessors方法中完成bean的实例化和执行

/**

    * Instantiate and invoke all registered BeanFactoryPostProcessor beans,

    * respecting explicit order if given.

    *

Must be called before singleton instantiation.

    */protectedvoidinvokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory){//开始执行beanFactoryPostProcessor对应实现类,需要知道的是beanFactoryPostProcessor是spring的扩展接口,在刷新容器之前,该接口可以用来修改bean元数据信息PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)if(beanFactory.getTempClassLoader() ==null&& beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {            beanFactory.addBeanPostProcessor(newLoadTimeWeaverAwareProcessor(beanFactory));            beanFactory.setTempClassLoader(newContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));        }    }

8、查看

invokeBeanFactoryPostProcessors的具体执行方法

publicstaticvoidinvokeBeanFactoryPostProcessors(

            ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors){// Invoke BeanDefinitionRegistryPostProcessors first, if any.Set processedBeans =newHashSet<>();if(beanFactoryinstanceofBeanDefinitionRegistry) {            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;            List regularPostProcessors =newArrayList<>();            List registryProcessors =newArrayList<>();//开始遍历三个内部类,如果属于BeanDefinitionRegistryPostProcessor子类,加入到bean注册的集合,否则加入到regularPostProcessorsfor(BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if(postProcessorinstanceofBeanDefinitionRegistryPostProcessor) {                    BeanDefinitionRegistryPostProcessor registryProcessor =                            (BeanDefinitionRegistryPostProcessor) postProcessor;                    registryProcessor.postProcessBeanDefinitionRegistry(registry);                    registryProcessors.add(registryProcessor);                }else{                    regularPostProcessors.add(postProcessor);                }            }// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!// Separate between BeanDefinitionRegistryPostProcessors that implement// PriorityOrdered, Ordered, and the rest.List currentRegistryProcessors =newArrayList<>();// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.//通过BeanDefinitionRegistryPostProcessor获取到对应的处理类“org.springframework.context.annotation.internalConfigurationAnnotationProcessor”,但是需要注意的是这个类在springboot中搜索不到,这个类的完全限定名在AnnotationConfigEmbeddedWebApplicationContext中,在进行初始化的时候会装配几个类,在创建AnnotatedBeanDefinitionReader对象的时候会将该类注册到bean对象中,此处可以看到internalConfigurationAnnotationProcessor为bean名称,容器中真正的类是ConfigurationClassPostProcessorString[] postProcessorNames =                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);//首先执行类型为PriorityOrdered的BeanDefinitionRegistryPostProcessor//PriorityOrdered类型表明为优先执行for(String ppName : postProcessorNames) {if(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){//获取对应的beancurrentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//用来存储已经执行过的BeanDefinitionRegistryPostProcessorprocessedBeans.add(ppName);                }            }            sortPostProcessors(currentRegistryProcessors, beanFactory);            registryProcessors.addAll(currentRegistryProcessors);//开始执行装配逻辑invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);            currentRegistryProcessors.clear();// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.//其次执行类型为Ordered的BeanDefinitionRegistryPostProcessor//Ordered表明按顺序执行postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);for(String ppName : postProcessorNames) {if(!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)){                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));                    processedBeans.add(ppName);                }            }            sortPostProcessors(currentRegistryProcessors, beanFactory);            registryProcessors.addAll(currentRegistryProcessors);            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);            currentRegistryProcessors.clear();// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.//循环中执行类型不为PriorityOrdered,Ordered类型的BeanDefinitionRegistryPostProcessorbooleanreiterate =true;while(reiterate) {                reiterate =false;                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,true,false);for(String ppName : postProcessorNames) {if(!processedBeans.contains(ppName)) {                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));                        processedBeans.add(ppName);                        reiterate =true;                    }                }                sortPostProcessors(currentRegistryProcessors, beanFactory);                registryProcessors.addAll(currentRegistryProcessors);                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);                currentRegistryProcessors.clear();            }// Now, invoke the postProcessBeanFactory callback of all processors handled so far.    //执行父类方法,优先执行注册处理类invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);//执行有规则处理类invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);        }else{// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);        }// Do not initialize FactoryBeans here: We need to leave all regular beans// uninitialized to let the bean factory post-processors apply to them!String[] postProcessorNames =                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class,true,false);// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,// Ordered, and the rest.List priorityOrderedPostProcessors =newArrayList<>();        List orderedPostProcessorNames =newArrayList<>();        List nonOrderedPostProcessorNames =newArrayList<>();for(String ppName : postProcessorNames) {if(processedBeans.contains(ppName)) {// skip - already processed in first phase above}elseif(beanFactory.isTypeMatch(ppName, PriorityOrdered.class)){                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));            }elseif(beanFactory.isTypeMatch(ppName, Ordered.class)){                orderedPostProcessorNames.add(ppName);            }else{                nonOrderedPostProcessorNames.add(ppName);            }        }// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.sortPostProcessors(priorityOrderedPostProcessors, beanFactory);        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// Next, invoke the BeanFactoryPostProcessors that implement Ordered.List orderedPostProcessors =newArrayList<>(orderedPostProcessorNames.size());for(String postProcessorName : orderedPostProcessorNames) {            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));        }        sortPostProcessors(orderedPostProcessors, beanFactory);        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// Finally, invoke all other BeanFactoryPostProcessors.List nonOrderedPostProcessors =newArrayList<>(nonOrderedPostProcessorNames.size());for(String postProcessorName : nonOrderedPostProcessorNames) {            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));        }        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);// Clear cached merged bean definitions since the post-processors might have// modified the original metadata, e.g. replacing placeholders in values...beanFactory.clearMetadataCache();    }

9、开始执行自动配置逻辑(启动类指定的配置,非默认配置),可以通过debug的方式一层层向里进行查找,会发现最终会在ConfigurationClassParser类中,此类是所有配置类的解析类,所有的解析逻辑在parser.parse(candidates)中

publicvoidparse(Set configCandidates){for(BeanDefinitionHolder holder : configCandidates) {            BeanDefinition bd = holder.getBeanDefinition();try{//是否是注解类if(bdinstanceofAnnotatedBeanDefinition) {                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());                }elseif(bdinstanceofAbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());                }else{                    parse(bd.getBeanClassName(), holder.getBeanName());                }            }catch(BeanDefinitionStoreException ex) {throwex;            }catch(Throwable ex) {thrownewBeanDefinitionStoreException("Failed to parse configuration class ["+ bd.getBeanClassName() +"]", ex);            }        }//执行配置类this.deferredImportSelectorHandler.process();    }-------------------protectedfinalvoidparse(AnnotationMetadata metadata, String beanName)throwsIOException{        processConfigurationClass(newConfigurationClass(metadata, beanName));    }-------------------protectedvoidprocessConfigurationClass(ConfigurationClass configClass)throwsIOException{if(this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;        }        ConfigurationClass existingClass =this.configurationClasses.get(configClass);if(existingClass !=null) {if(configClass.isImported()) {if(existingClass.isImported()) {                    existingClass.mergeImportedBy(configClass);                }// Otherwise ignore new imported config class; existing non-imported class overrides it.return;            }else{// Explicit bean definition found, probably replacing an import.// Let's remove the old one and go with the new one.this.configurationClasses.remove(configClass);this.knownSuperclasses.values().removeIf(configClass::equals);            }        }// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass = asSourceClass(configClass);do{//循环处理bean,如果有父类,则处理父类,直至结束sourceClass = doProcessConfigurationClass(configClass, sourceClass);        }while(sourceClass !=null);this.configurationClasses.put(configClass, configClass);    }

10、继续跟进

doProcessConfigurationClass方法,此方式是支持注解配置的核心逻辑

/**    * Apply processing and build a complete {@linkConfigurationClass} by reading the    * annotations, members and methods from the source class. This method can be called    * multiple times as relevant sources are discovered.    *@paramconfigClass the configuration class being build    *@paramsourceClass a source class    *@returnthe superclass, or {@codenull} if none found or previously processed    */@NullableprotectedfinalSourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)            throws IOException {//处理内部类逻辑,由于传来的参数是启动类,并不包含内部类,所以跳过if(configClass.getMetadata().isAnnotated(Component.class.getName())) {// Recursively process any member (nested) classes firstprocessMemberClasses(configClass, sourceClass);        }// Process any @PropertySource annotations//针对属性配置的解析for(AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(                sourceClass.getMetadata(), PropertySources.class,org.springframework.context.annotation.PropertySource.class)) {if(this.environment instanceof ConfigurableEnvironment) {                processPropertySource(propertySource);            }else{                logger.info("Ignoring @PropertySource annotation on ["+ sourceClass.getMetadata().getClassName() +"]. Reason: Environment must implement ConfigurableEnvironment");            }        }// Process any @ComponentScan annotations// 这里是根据启动类@ComponentScan注解来扫描项目中的beanSet componentScans = AnnotationConfigUtils.attributesForRepeatable(                sourceClass.getMetadata(), ComponentScans.class,ComponentScan.class);if(!componentScans.isEmpty() &&                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for(AnnotationAttributes componentScan : componentScans) {// The config class is annotated with @ComponentScan -> perform the scan immediately//遍历项目中的bean,如果是注解定义的bean,则进一步解析Set scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// Check the set of scanned definitions for any further config classes and parse recursively if neededfor(BeanDefinitionHolder holder : scannedBeanDefinitions) {                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();if(bdCand ==null) {                        bdCand = holder.getBeanDefinition();                    }if(ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand,this.metadataReaderFactory)) {//递归解析,所有的bean,如果有注解,会进一步解析注解中包含的beanparse(bdCand.getBeanClassName(), holder.getBeanName());                    }                }            }        }// Process any @Import annotations//递归解析,获取导入的配置类,很多情况下,导入的配置类中会同样包含导入类注解processImports(configClass, sourceClass, getImports(sourceClass),true);// Process any @ImportResource annotations//解析@ImportResource配置类AnnotationAttributes importResource =                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);if(importResource !=null) {            String[] resources = importResource.getStringArray("locations");            Class readerClass = importResource.getClass("reader");for(String resource : resources) {                String resolvedResource =this.environment.resolveRequiredPlaceholders(resource);                configClass.addImportedResource(resolvedResource, readerClass);            }        }// Process individual @Bean methods//处理@Bean注解修饰的类Set beanMethods = retrieveBeanMethodMetadata(sourceClass);for(MethodMetadata methodMetadata : beanMethods) {            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));        }// Process default methods on interfaces// 处理接口中的默认方法processInterfaces(configClass, sourceClass);// Process superclass, if any//如果该类有父类,则继续返回,上层方法判断不为空,则继续递归执行if(sourceClass.getMetadata().hasSuperClass()) {            String superclass = sourceClass.getMetadata().getSuperClassName();if(superclass !=null&& !superclass.startsWith("java") &&                    !this.knownSuperclasses.containsKey(superclass)) {this.knownSuperclasses.put(superclass, configClass);// Superclass found, return its annotation metadata and recursereturnsourceClass.getSuperClass();            }        }// No superclass -> processing is completereturnnull;    }

11、查看获取配置类的逻辑

processImports(configClass, sourceClass, getImports(sourceClass),true);/**    * Returns {@code@Import} class, considering all meta-annotations.    */privateSet getImports(SourceClass sourceClass) throws IOException {        Set imports = new LinkedHashSet<>();        Set visited = new LinkedHashSet<>();        collectImports(sourceClass, imports, visited);returnimports;    }------------------/**    * Recursively collect all declared {@code@Import} values. Unlike most    * meta-annotations it is valid to have several {@code@Import}s declared with    * different values; the usual process of returning values from the first    * meta-annotation on a class is not sufficient.    *

For example, it is common for a {@code@Configuration} class to declare direct    * {@code@Import}s in addition to meta-imports originating from an {@code@Enable}    * annotation.    * 看到所有的bean都以导入的方式被加载进去    */privatevoid collectImports(SourceClass sourceClass, Set imports, Set visited)            throws IOException {if(visited.add(sourceClass)) {for(SourceClassannotation: sourceClass.getAnnotations()) {                String annName =annotation.getMetadata().getClassName();if(!annName.equals(Import.class.getName())) {                    collectImports(annotation, imports, visited);                }            }            imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(),"value"));        }    }

12、继续回到ConfigurationClassParser中的parse方法中的最后一行,继续跟进该方法:

this.deferredImportSelectorHandler.process()-------------publicvoid process() {            List deferredImports =this.deferredImportSelectors;this.deferredImportSelectors =null;try{if(deferredImports !=null) {                    DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();                    deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);                    deferredImports.forEach(handler::register);                    handler.processGroupImports();                }            }finally{this.deferredImportSelectors = new ArrayList<>();            }        }---------------publicvoid processGroupImports() {for(DeferredImportSelectorGrouping grouping :this.groupings.values()) {                grouping.getImports().forEach(entry -> {                    ConfigurationClass configurationClass =this.configurationClasses.get(                            entry.getMetadata());try{                        processImports(configurationClass, asSourceClass(configurationClass),                                asSourceClasses(entry.getImportClassName()),false);                    }catch(BeanDefinitionStoreException ex) {throwex;                    }catch(Throwable ex) {thrownew BeanDefinitionStoreException("Failed to process import candidates for configuration class ["+                                        configurationClass.getMetadata().getClassName() +"]", ex);                    }                });            }        }------------/**        * Return the imports defined by the group.        *@returneach import with its associated configuration class        */publicIterable getImports() {for(DeferredImportSelectorHolder deferredImport :this.deferredImports) {this.group.process(deferredImport.getConfigurationClass().getMetadata(),                        deferredImport.getImportSelector());            }returnthis.group.selectImports();        }    }------------publicDeferredImportSelector getImportSelector() {returnthis.importSelector;        }------------@Overridepublicvoid process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {            Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,                    () -> String.format("Only %s implementations are supported, got %s",                            AutoConfigurationImportSelector.class.getSimpleName(),                            deferredImportSelector.getClass().getName()));            AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)                    .getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);this.autoConfigurationEntries.add(autoConfigurationEntry);for(String importClassName : autoConfigurationEntry.getConfigurations()) {this.entries.putIfAbsent(importClassName, annotationMetadata);            }        }

如何理解springboot中的starter?

使用spring+springmvc框架进行开发的时候,如果需要引入mybatis框架,那么需要在xml中定义需要的bean对象,这个过程很明显是很麻烦的,如果需要引入额外的其他组件,那么也需要进行复杂的配置,因此在springboot中引入了starter

starter就是一个jar包,写一个@Configuration的配置类,将这些bean定义在其中,然后再starter包的META-INF/spring.factories中写入配置类,那么springboot程序在启动的时候就会按照约定来加载该配置类

开发人员只需要将相应的starter包依赖进应用中,进行相关的属性配置,就可以进行代码开发,而不需要单独进行bean对象的配置

你可能感兴趣的:(谈起SpringBoot,面试官必问:讲述一下 SpringBoot 自动装配原理?)