前言
關于@Import注解的使用无拗,在Spring源碼中隨處可見,其作用大家基本也都知道遣总,無非就是注入指定的Bean到Spring IOC容器管理昌抠,只能作用用于類上患朱,其用法分三種:普通的類直接注入、實現(xiàn)了ImportSelector接口的類炊苫、實現(xiàn)了ImportBeanDefinitionRegistrar接口的類麦乞,那么Spring具體是如何實現(xiàn)的?這三種方式又有何不同劝评?一起跟進源碼一探究竟姐直,徹底了解Import的實現(xiàn)。
源碼追蹤(Spring版本:5.3.6-SNAPSHOT)
眾所周知Spring需要先初始化上下文容器蒋畜,Spring上下文容器針對不同的場景設計了較多類型声畏,不過都大同小異,這里拿其中的AnnotationConfigApplicationContext進行講解姻成,如果需要進一步了解Spring的每一個容器或者Spring的更多源碼細節(jié)插龄,可關注我,我會在后面的章節(jié)中逐步揭開Spring源碼迷霧科展。
您的認可是我前進的動力均牢,如果您覺得可以請關注我并轉發(fā)文章,謝謝2哦谩E枪颉!
AnnotationConfigApplicationContext(AbstractApplicationContext)
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
? // 注解配置上下文初始化
? this();
? // 將配置組件(AppConfig)注冊到AnnotationConfigApplicationContext上下文對象的beanFactory中(即將bean信息放入beanDefinitionMap中)
? register(componentClasses);
? // 刷新注冊到AnnotationConfigApplicationContext上下文對象的相關屬性
? 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上下文對象的BeanFactory并返回BeanFactory對象
? ? ? 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");
? ? ? ? // 實例化并調(diào)用所有已注冊的BeanFactoryPostProcessor的Bean到Spring容器中.
? ? ? ? invokeBeanFactoryPostProcessors(beanFactory);
? ? ......
? ? ? ? // 實例化所有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
? ? ? // (這個bean不是直接存在的琅攘,在AnnotationConfigUtils類中可查到其對應的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添加到當前注冊Bean的處理對象集合
? ? ? ? ? ? currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
? ? ? ? ? ? processedBeans.add(ppName);
? ? ? ? }
? ? ? }
? ? ? // 將BeanDefinitionRegistryPostProcessor排序
? ? ? sortPostProcessors(currentRegistryProcessors, beanFactory);
? ? ? // 將BeanDefinitionRegistryPostProcessor稍后注冊到BeanFactory
? ? ? registryProcessors.addAll(currentRegistryProcessors);
? ? ? //
? ? ? invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
? ? ? currentRegistryProcessors.clear();
? ? ? ......
}
通過調(diào)用PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors方法循環(huán)執(zhí)行所有BeanDefinitionRegistryPostProcessor垮庐,將相關Bean注入BeanFacotry。這里通過調(diào)用ConfigurationClassPostProcessor 處理所有@Configuration配置類坞琴,其通過核心方法processConfigBeanDefinitions來處理相關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,防止被重復調(diào)用
? this.factoriesPostProcessed.add(factoryId);
? if (!this.registriesPostProcessed.contains(factoryId)) {
? ? ? // 注入標有@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);
? ? ? // 檢查當前Bean是否已當作配置類處理過
? ? ? if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
? ? ? ? if (logger.isDebugEnabled()) {
? ? ? ? ? ? logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
? ? ? ? }
? ? ? }
? ? ? // 檢查當前Bean是否是配置類,如果是則添加到configCandidates中剧辐,后面進行處理
? ? ? 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;
? }
? ......
? // 準備解析 @Configuration 標注的類寒亥,構建解析對象
? ConfigurationClassParser parser = new ConfigurationClassParser(
? ? ? ? this.metadataReaderFactory, this.problemReporter, this.environment,
? ? ? ? this.resourceLoader, this.componentScanBeanNameGenerator, registry);
? // 配置Bean去重
? Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
? // 存儲已解析過的配置類
? Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
? // 循環(huán)解析
? do {
? ? ? StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
? ? ? // 解析所有@Configuration標記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對@Configuration類進行解析溉奕。
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;
? }
? // 標識該配置類是否解析過
? ConfigurationClass existingClass = this.configurationClasses.get(configClass);
? ......
? // Recursively process the configuration class and its superclass hierarchy.
? // 將配置類轉為SourceClass類
? SourceClass sourceClass = asSourceClass(configClass, filter);
? // 從當前配置類configClass開始向上沿著類繼承結構逐層執(zhí)行doProcessConfigurationClass,
// 直到遇到的父類是由Java提供的類結束循環(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注解存在繼承關系挟纱,遞歸處理嵌套類
? if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
? ? ? // Recursively process any member (nested) classes first
? ? ? processMemberClasses(configClass, sourceClass, filter);
? }
? ......
? // 重點來了,在這里處理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 當前源碼類
? * @Param importCandidates 所有的@Import注解的value
? * @Param exclusionFilter 需要排除的類
? * @Param checkForCircularImports 是否檢查循環(huán)導入
? **/
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)處理每一個@Import,每個@Import可能導入三種類型的類 :
? ? ? ? ? // 1. ImportSelector
? ? ? ? ? // 2. ImportBeanDefinitionRegistrar
? ? ? ? ? // 3. 其他類型腐宋,都當作配置類處理,也就是相當于使用了注解@Configuration的配置類
? ? ? ? // 下面的for循環(huán)中對這三種情況執(zhí)行了不同的處理邏輯
? ? ? ? for (SourceClass candidate : importCandidates) {
? ? ? ? ? ? // 處理ImportSelector類(Spring Boot的自動裝配采用的是這種方式)
? ? ? ? ? ? if (candidate.isAssignable(ImportSelector.class)) {
? ? ? ? ? ? ? // 加載對應的ImportSelector實現(xiàn)類
? ? ? ? ? ? ? Class<?> candidateClass = candidate.loadClass();
? ? ? ? ? ? ? // 實例化對應的實現(xiàn)ImportSelector的類
? ? ? ? ? ? ? ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
? ? ? ? ? ? ? ? ? ? this.environment, this.resourceLoader, this.registry);
? ? ? ? ? ? ? // 獲取ImportSelector類中需要排除的實例化的類
? ? ? ? ? ? ? Predicate<String> selectorFilter = selector.getExclusionFilter();
? ? ? ? ? ? ? if (selectorFilter != null) {
? ? ? ? ? ? ? ? ? exclusionFilter = exclusionFilter.or(selectorFilter);
? ? ? ? ? ? ? }
? ? ? ? ? ? ? // 后置處理類交由后置處理器進行處理檀轨,本類涵蓋代碼的第18行代碼處理(this.deferredImportSelectorHandler.process();)
? ? ? ? ? ? ? if (selector instanceof DeferredImportSelector) {
? ? ? ? ? ? ? ? ? this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
? ? ? ? ? ? ? }
? ? ? ? ? ? ? else {
? ? ? ? ? ? ? ? ? // 調(diào)用實現(xiàn)ImportSelector的類的selectImports胸竞,獲取需要實例化類的className
? ? ? ? ? ? ? ? ? String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
? ? ? ? ? ? ? ? ? // 從當前ImportSelector需要實例化的類開始向上沿著類繼承結構逐層執(zhí)行將className加入到BeanFactory的beanDefinitionMap中(要排除的類除外),
? ? ? ? ? ? ? ? // 直到遇到的父類是由Java提供的類結束循環(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();
? ? ? ? ? ? ? // 直接實例化ImportBeanDefinitionRegistrar 類
? ? ? ? ? ? ? ImportBeanDefinitionRegistrar registrar =
? ? ? ? ? ? ? ? ? ? ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
? ? ? ? ? ? ? ? ? ? ? ? ? this.environment, this.resourceLoader, this.registry);
? ? ? ? ? ? ? // 將ImportBeanDefinitionRegistrar 類加入到importBeanDefinitionRegistrars集合中
? ? ? ? ? ? ? // 會在ConfigurationClassPostProcessor第69行代碼進行處理
? ? ? ? ? ? ? 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中等待實例化(ImportBeanDefinitionRegistrar類型的Bean需要通過下面的方式處理才能放入)参萄,回到ConfigurationClassPostProcessor的69行代碼(this.reader.loadBeanDefinitions(configClasses);)卫枝,調(diào)用ConfigurationClassBeanDefinitionReader#loadBeanDefinitions進行處理。
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進行處理
? 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的所有類已注冊到BeanFactory中讹挎,那么什么時候?qū)@些類進行初始化呢校赤?回到AnnotationConfigApplicationContext(即AbstractApplicationContext)的refresh方法,通過finishBeanFactoryInitialization(beanFactory)實例化Bean筒溃。