深入剖析Spring boot自動(dòng)裝配原理二(@Import)

前言

關(guān)于@Import注解的使用,在Spring源碼中隨處可見,其作用大家基本也都知道,無非就是注入指定的Bean到Spring IOC容器管理,只能作用用于類上,其用法分三種:普通的類直接注入、實(shí)現(xiàn)了ImportSelector接口的類、實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口的類,那么Spring具體是如何實(shí)現(xiàn)的?這三種方式又有何不同?一起跟進(jìn)源碼一探究竟,徹底了解Import的實(shí)現(xiàn)。

源碼追蹤(Spring版本:5.3.6-SNAPSHOT

眾所周知Spring需要先初始化上下文容器,Spring上下文容器針對(duì)不同的場(chǎng)景設(shè)計(jì)了較多類型,不過都大同小異,這里拿其中的AnnotationConfigApplicationContext進(jìn)行講解,如果需要進(jìn)一步了解Spring的每一個(gè)容器或者Spring的更多源碼細(xì)節(jié),可關(guān)注我,我會(huì)在后面的章節(jié)中逐步揭開Spring源碼迷霧。

您的認(rèn)可是我前進(jìn)的動(dòng)力,如果您覺得可以請(qǐng)關(guān)注我并轉(zhuǎn)發(fā)文章,謝謝?。?!

AnnotationConfigApplicationContext(AbstractApplicationContext)

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {

? // 注解配置上下文初始化

? this();

? // 將配置組件(AppConfig)注冊(cè)到AnnotationConfigApplicationContext上下文對(duì)象的beanFactory中(即將bean信息放入beanDefinitionMap中)

? register(componentClasses);

? // 刷新注冊(cè)到AnnotationConfigApplicationContext上下文對(duì)象的相關(guān)屬性

? refresh();

}

@Override

// AbstractApplicationContext公共方法

public void refresh() throws BeansException, IllegalStateException {

? synchronized (this.startupShutdownMonitor) {

? ? ? StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

? ? ? // Prepare this context for refreshing.

? ? ? prepareRefresh();

? ? ? // 刷新AnnotationConfigApplicationContext上下文對(duì)象的BeanFactory并返回BeanFactory對(duì)象

? ? ? 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);

? ? ? ? StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

? ? ? ? // 實(shí)例化并調(diào)用所有已注冊(cè)的BeanFactoryPostProcessor的Bean到Spring容器中.

? ? ? ? invokeBeanFactoryPostProcessors(beanFactory);

? ? ......

? ? ? ? // 實(shí)例化所有BeanFactory中非延遲加載的Bean.

? ? ? ? finishBeanFactoryInitialization(beanFactory);

? ? ? ? // Last step: publish corresponding event.

? ? ? ? finishRefresh();

? ? ? }

? ? ......

}

PostProcessorRegistrationDelegate

public static void invokeBeanFactoryPostProcessors(

? ? ? ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

? ......

? ? ? // 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<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

? ? ? // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.

? ? ? // 獲取BeanDefinitionRegistryPostProcessor類型的bean名稱,注意這里獲取到了名字為

? ? ? // org.springframework.context.annotation.internalConfigurationAnnotationProcessor的bean

? ? ? // (這個(gè)bean不是直接存在的,在AnnotationConfigUtils類中可查到其對(duì)應(yīng)的Ben為ConfigurationClassPostProcessor)

? ? ? String[] postProcessorNames =

? ? ? ? ? ? beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

? ? ? for (String ppName : postProcessorNames) {

? ? ? ? if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {

? ? ? ? ? ? // beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)獲取到ConfigurationClassPostProcessor

? ? ? ? ? ? // 將ConfigurationClassPostProcessor添加到當(dāng)前注冊(cè)Bean的處理對(duì)象集合

? ? ? ? ? ? currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));

? ? ? ? ? ? processedBeans.add(ppName);

? ? ? ? }

? ? ? }

? ? ? // 將BeanDefinitionRegistryPostProcessor排序

? ? ? sortPostProcessors(currentRegistryProcessors, beanFactory);

? ? ? // 將BeanDefinitionRegistryPostProcessor稍后注冊(cè)到BeanFactory

? ? ? registryProcessors.addAll(currentRegistryProcessors);

? ? ? //

? ? ? invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());

? ? ? currentRegistryProcessors.clear();

? ? ? ......

}

通過調(diào)用PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors方法循環(huán)執(zhí)行所有BeanDefinitionRegistryPostProcessor,將相關(guān)Bean注入BeanFacotry。這里通過調(diào)用ConfigurationClassPostProcessor 處理所有@Configuration配置類,其通過核心方法processConfigBeanDefinitions來處理相關(guān)Bean的注入。

ConfigurationClassPostProcessor

@Override

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {

? // 生成處理ID

? int factoryId = System.identityHashCode(beanFactory);

? // 判斷后置處理器在registriesPostProcessed和factoriesPostProcessed中有沒有被調(diào)用過

? if (this.factoriesPostProcessed.contains(factoryId)) {

? ? ? throw new IllegalStateException(

? ? ? ? ? ? "postProcessBeanFactory already called on this post-processor against " + beanFactory);

? }

? // 調(diào)用前保存factoryId,防止被重復(fù)調(diào)用

? this.factoriesPostProcessed.add(factoryId);

? if (!this.registriesPostProcessed.contains(factoryId)) {

? ? ? // 注入標(biāo)有@configuration的Bean里面需要注入的類(如:@Import注解)

? ? ? processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);

? }

? enhanceConfigurationClasses(beanFactory);

? beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));

}

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

? // 需要處理的候選@configuration類

? List<BeanDefinitionHolder> configCandidates = new ArrayList<>();

? // 獲取BeanFactory中注入的所有beanDefinitionNames

? String[] candidateNames = registry.getBeanDefinitionNames();

? for (String beanName : candidateNames) {

? ? ? BeanDefinition beanDef = registry.getBeanDefinition(beanName);

? ? ? // 檢查當(dāng)前Bean是否已當(dāng)作配置類處理過

? ? ? if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {

? ? ? ? if (logger.isDebugEnabled()) {

? ? ? ? ? ? logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);

? ? ? ? }

? ? ? }

? ? ? // 檢查當(dāng)前Bean是否是配置類,如果是則添加到configCandidates中,后面進(jìn)行處理

? ? ? 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;

? }

? ......

? // 準(zhǔn)備解析 @Configuration 標(biāo)注的類,構(gòu)建解析對(duì)象

? ConfigurationClassParser parser = new ConfigurationClassParser(

? ? ? ? this.metadataReaderFactory, this.problemReporter, this.environment,

? ? ? ? this.resourceLoader, this.componentScanBeanNameGenerator, registry);

? // 配置Bean去重

? Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);

? // 存儲(chǔ)已解析過的配置類

? Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());

? // 循環(huán)解析

? do {

? ? ? StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");

? ? ? // 解析所有@Configuration標(biāo)記Bean,并將解析的Bean信息存入ConfigurationClassParser的configurationClasses集合中

? ? ? 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());

? ? ? }

? ? ? // 初始化所有配置類中的Bean(包含處理ImportBeanDefinitionRegistrars類),

? ? ? // 并將其放入Spring容器中(BeanFactory的beanDefinitionMap)

? ? ? this.reader.loadBeanDefinitions(configClasses);

? ? ? alreadyParsed.addAll(configClasses);

? ? ? processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

? ? ? candidates.clear();

? ? ? ......

? }

? while (!candidates.isEmpty());

? ......

}

通過調(diào)用ConfigurationClassParser#parse對(duì)@Configuration類進(jìn)行解析。

ConfigurationClassParser

public void parse(Set<BeanDefinitionHolder> configCandidates) {

? for (BeanDefinitionHolder holder : configCandidates) {

? ? ? BeanDefinition bd = holder.getBeanDefinition();

? ? ? try {

? ? ? ? if (bd instanceof AnnotatedBeanDefinition) {

? ? ? ? ? ? // Configuration類為AnnotatedBean

? ? ? ? ? ? parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());

? ? ? ? }

? ? ? ? else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {

? ? ? ? ? ? parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());

? ? ? ? }

? ? ? ? else {

? ? ? ? ? ? parse(bd.getBeanClassName(), holder.getBeanName());

? ? ? ? }

? ? ? }

? ? ? ......

? }

? this.deferredImportSelectorHandler.process();

}

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {

? processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);

}

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {

? // 判斷是否需要跳過該配置類的解析(例如配置了@Conditional注解)

? if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {

? ? ? return;

? }

? // 標(biāo)識(shí)該配置類是否解析過

? ConfigurationClass existingClass = this.configurationClasses.get(configClass);

? ......

? // Recursively process the configuration class and its superclass hierarchy.

? // 將配置類轉(zhuǎn)為SourceClass類

? SourceClass sourceClass = asSourceClass(configClass, filter);

? // 從當(dāng)前配置類configClass開始向上沿著類繼承結(jié)構(gòu)逐層執(zhí)行doProcessConfigurationClass,

// 直到遇到的父類是由Java提供的類結(jié)束循環(huán)

? do {

? ? ? sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);

? }

? while (sourceClass != null);

? this.configurationClasses.put(configClass, configClass);

}

@Nullable

protected final SourceClass doProcessConfigurationClass(

? ? ? ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)

? ? ? throws IOException {

? ? // Component注解存在繼承關(guān)系,遞歸處理嵌套類

? if (configClass.getMetadata().isAnnotated(Component.class.getName())) {

? ? ? // Recursively process any member (nested) classes first

? ? ? processMemberClasses(configClass, sourceClass, filter);

? }

? ......

? // 重點(diǎn)來了,在這里處理Import注解

? processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

? ......

? // 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 recurse

? ? ? ? return sourceClass.getSuperClass();

? ? ? }

? }

? // No superclass -> processing is complete

? return null;

}

/**

? * 處理配置類上搜集到的@Import注解

? * @Param configuClass 配置類

? * @Param currentSourceClass 當(dāng)前源碼類

? * @Param importCandidates 所有的@Import注解的value

? * @Param exclusionFilter 需要排除的類

? * @Param checkForCircularImports 是否檢查循環(huán)導(dǎo)入

? **/

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,

? ? ? Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,

? ? ? boolean checkForCircularImports) {

? if (importCandidates.isEmpty()) {

? ? ? return;

? }

? if (checkForCircularImports && isChainedImportOnStack(configClass)) {

? ? ? this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));

? }

? else {

? ? ? // 開始處理配置類configClass上@Import所有的importCandidates

? ? ? this.importStack.push(configClass);

? ? ? try {

? ? ? ? ? // 循環(huán)處理每一個(gè)@Import,每個(gè)@Import可能導(dǎo)入三種類型的類 :

? ? ? ? ? // 1. ImportSelector

? ? ? ? ? // 2. ImportBeanDefinitionRegistrar

? ? ? ? ? // 3. 其他類型,都當(dāng)作配置類處理,也就是相當(dāng)于使用了注解@Configuration的配置類

? ? ? ? // 下面的for循環(huán)中對(duì)這三種情況執(zhí)行了不同的處理邏輯

? ? ? ? for (SourceClass candidate : importCandidates) {

? ? ? ? ? ? // 處理ImportSelector類(Spring Boot的自動(dòng)裝配采用的是這種方式)

? ? ? ? ? ? if (candidate.isAssignable(ImportSelector.class)) {

? ? ? ? ? ? ? // 加載對(duì)應(yīng)的ImportSelector實(shí)現(xiàn)類

? ? ? ? ? ? ? Class<?> candidateClass = candidate.loadClass();

? ? ? ? ? ? ? // 實(shí)例化對(duì)應(yīng)的實(shí)現(xiàn)ImportSelector的類

? ? ? ? ? ? ? ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,

? ? ? ? ? ? ? ? ? ? this.environment, this.resourceLoader, this.registry);

? ? ? ? ? ? ? // 獲取ImportSelector類中需要排除的實(shí)例化的類

? ? ? ? ? ? ? Predicate<String> selectorFilter = selector.getExclusionFilter();

? ? ? ? ? ? ? if (selectorFilter != null) {

? ? ? ? ? ? ? ? ? exclusionFilter = exclusionFilter.or(selectorFilter);

? ? ? ? ? ? ? }

? ? ? ? ? ? ? // 后置處理類交由后置處理器進(jìn)行處理,本類涵蓋代碼的第18行代碼處理(this.deferredImportSelectorHandler.process();)

? ? ? ? ? ? ? if (selector instanceof DeferredImportSelector) {

? ? ? ? ? ? ? ? ? this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);

? ? ? ? ? ? ? }

? ? ? ? ? ? ? else {

? ? ? ? ? ? ? ? ? // 調(diào)用實(shí)現(xiàn)ImportSelector的類的selectImports,獲取需要實(shí)例化類的className

? ? ? ? ? ? ? ? ? String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());

? ? ? ? ? ? ? ? ? // 從當(dāng)前ImportSelector需要實(shí)例化的類開始向上沿著類繼承結(jié)構(gòu)逐層執(zhí)行將className加入到BeanFactory的beanDefinitionMap中(要排除的類除外),

? ? ? ? ? ? ? ? // 直到遇到的父類是由Java提供的類結(jié)束循環(huán)

? ? ? ? ? ? ? ? ? Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);

? ? ? ? ? ? ? ? ? // 循環(huán)處理importClassNames類中再包含的import類

? ? ? ? ? ? ? ? ? processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);

? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? ? ? else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {

? ? ? ? ? ? ? // Candidate class is an ImportBeanDefinitionRegistrar ->

? ? ? ? ? ? ? // delegate to it to register additional bean definitions

? ? ? ? ? ? ? Class<?> candidateClass = candidate.loadClass();

? ? ? ? ? ? ? // 直接實(shí)例化ImportBeanDefinitionRegistrar 類

? ? ? ? ? ? ? ImportBeanDefinitionRegistrar registrar =

? ? ? ? ? ? ? ? ? ? ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,

? ? ? ? ? ? ? ? ? ? ? ? ? this.environment, this.resourceLoader, this.registry);

? ? ? ? ? ? ? // 將ImportBeanDefinitionRegistrar 類加入到importBeanDefinitionRegistrars集合中

? ? ? ? ? ? ? // 會(huì)在ConfigurationClassPostProcessor第69行代碼進(jìn)行處理

? ? ? ? ? ? ? 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());

? ? ? ? ? ? ? // 非ImportSelector or ImportBeanDefinitionRegistrar直接處理,放入BeanFactory中

? ? ? ? ? ? ? processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);

? ? ? ? ? ? }

? ? ? ? }

? ? ? }

? ? ? ......

? }

}

通過以上的步驟已將Import中的類注入到BeanFacotry的beanDefinitionMap中等待實(shí)例化(ImportBeanDefinitionRegistrar類型的Bean需要通過下面的方式處理才能放入),回到ConfigurationClassPostProcessor的69行代碼(this.reader.loadBeanDefinitions(configClasses);),調(diào)用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions進(jìn)行處理。

ConfigurationClassBeanDefinitionReader

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {

? TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();

? for (ConfigurationClass configClass : configurationModel) {

? ? ? loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);

? }

}

private void loadBeanDefinitionsForConfigurationClass(

? ? ? ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

? ......

? loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());

? // 獲取所有ImportBeanDefinitionRegistrars進(jìn)行處理

? loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());

}

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {

? registrars.forEach((registrar, metadata) ->

? ? ? ? // 調(diào)用繼承ImportBeanDefinitionRegistrar類中的registerBeanDefinitions將Bean注入到BeanFactory

? ? ? ? registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator));

}

到這一步Import的所有類已注冊(cè)到BeanFactory中,那么什么時(shí)候?qū)@些類進(jìn)行初始化呢?回到AnnotationConfigApplicationContext(即AbstractApplicationContext)的refresh方法,通過finishBeanFactoryInitialization(beanFactory)實(shí)例化Bean。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容