前言
前面的文章描述了Application對應Bean的創建,本篇將闡述spring boot中bean的創建過程
?
refresh
?
首先來看SpringApplication#run方法中refresh()方法
[html]?view plain?copy
//?Refresh?the?context??????????????refresh(context);??
調用的是AbstractApplicationContext中的refresh方法
[html]?view plain?copy
protected?void?refresh(ApplicationContext?applicationContext)?{??????????Assert.isInstanceOf(AbstractApplicationContext.class,?applicationContext);??????????((AbstractApplicationContext)?applicationContext).refresh();??????}??
方法定義如下:
[html]?view plain?copy
public?void?refresh()?throws?BeansException,?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);????????????????????//?Register?bean?processors?that?intercept?bean?creation.??????????????????registerBeanPostProcessors(beanFactory);????????????????????//?Initialize?message?source?for?this?context.??????????????????initMessageSource();????????????????????//?Initialize?event?multicaster?for?this?context.??????????????????initApplicationEventMulticaster();????????????????????//?Initialize?other?special?beans?in?specific?context?subclasses.??????????????????onRefresh();????????????????????//?Check?for?listener?beans?and?register?them.??????????????????registerListeners();????????????????????//?Instantiate?all?remaining?(non-lazy-init)?singletons.??????????????????finishBeanFactoryInitialization(beanFactory);????????????????????//?Last?step:?publish?corresponding?event.??????????????????finishRefresh();??????????????}????????????????catch?(BeansException?ex)?{??????????????????logger.warn("Exception?encountered?during?context?initialization?-?cancelling?refresh?attempt",?ex);????????????????????//?Destroy?already?created?singletons?to?avoid?dangling?resources.??????????????????destroyBeans();????????????????????//?Reset?'active'?flag.??????????????????cancelRefresh(ex);????????????????????//?Propagate?exception?to?caller.??????????????????throw?ex;??????????????}??????????}??????}??
該方法中涉及的過程非常多,需要一步步來分析
?
獲取BeanFactory
[html]?view plain?copy
ConfigurableListableBeanFactory?beanFactory?=?obtainFreshBeanFactory();??
通過前面的文章應該知道對應的BeanFactory為DefaultListableBeanFactory
?
直奔主題來看如下方法
[html]?view plain?copy
invokeBeanFactoryPostProcessors(beanFactory);??
?
[html]?view plain?copy
protected?void?invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory?beanFactory)?{??????????PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory,?getBeanFactoryPostProcessors());??????}??
首先來看getBeanFactoryPostProcessors(),其對應值為:ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor、PropertySourceOrderingPostProcessor
?
ConfigurationWarningsApplicationContextInitializer是在ConfigurationWarningsApplicationContextInitializer中執行
[html]?view plain?copy
public?void?initialize(ConfigurableApplicationContext?context)?{??????????context.addBeanFactoryPostProcessor(new?ConfigurationWarningsPostProcessor(??????????????????getChecks()));??????}??
添加
PropertySourceOrderingPostProcessor是在ConfigFileApplicationListener執行
[html]?view plain?copy
protected?void?addPostProcessors(ConfigurableApplicationContext?context)?{??????????context.addBeanFactoryPostProcessor(new?PropertySourceOrderingPostProcessor(??????????????????context));??????}??
添加
來看invokeBeanFactoryPostProcessors方法
?
[html]?view plain?copy
public?static?void?invokeBeanFactoryPostProcessors(??????????????ConfigurableListableBeanFactory?beanFactory,?List<BeanFactoryPostProcessor>?beanFactoryPostProcessors)?{????????????//?Invoke?BeanDefinitionRegistryPostProcessors?first,?if?any.??????????Set<String>?processedBeans?=?new?HashSet<String>();????????????if?(beanFactory?instanceof?BeanDefinitionRegistry)?{??????????????...//處理后處理器?????????????????????????????String[]?postProcessorNames?=??????????????????????beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,?true,?false);????????????????//?First,?invoke?the?BeanDefinitionRegistryPostProcessors?that?implement?PriorityOrdered.??????????????List<BeanDefinitionRegistryPostProcessor>?priorityOrderedPostProcessors?=?new?ArrayList<BeanDefinitionRegistryPostProcessor>();??????????????for?(String?ppName?:?postProcessorNames)?{??????????????????if?(beanFactory.isTypeMatch(ppName,?PriorityOrdered.class))?{??????????????????????priorityOrderedPostProcessors.add(beanFactory.getBean(ppName,?BeanDefinitionRegistryPostProcessor.class));??????????????????????processedBeans.add(ppName);??????????????????}??????????????}??????????????OrderComparator.sort(priorityOrderedPostProcessors);??????????????registryPostProcessors.addAll(priorityOrderedPostProcessors);??????????????invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors,?registry);????????????????//?Next,?invoke?the?BeanDefinitionRegistryPostProcessors?that?implement?Ordered.??????????????postProcessorNames?=?beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,?true,?false);??????????????List<BeanDefinitionRegistryPostProcessor>?orderedPostProcessors?=?new?ArrayList<BeanDefinitionRegistryPostProcessor>();??????????????for?(String?ppName?:?postProcessorNames)?{??????????????????if?(!processedBeans.contains(ppName)?&&?beanFactory.isTypeMatch(ppName,?Ordered.class))?{??????????????????????orderedPostProcessors.add(beanFactory.getBean(ppName,?BeanDefinitionRegistryPostProcessor.class));??????????????????????processedBeans.add(ppName);??????????????????}??????????????}??????????????OrderComparator.sort(orderedPostProcessors);??????????????registryPostProcessors.addAll(orderedPostProcessors);??????????????invokeBeanDefinitionRegistryPostProcessors(orderedPostProcessors,?registry);????????????????//?Finally,?invoke?all?other?BeanDefinitionRegistryPostProcessors?until?no?further?ones?appear.??????????????boolean?reiterate?=?true;??????????????while?(reiterate)?{??????????????????reiterate?=?false;??????????????????postProcessorNames?=?beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,?true,?false);??????????????????for?(String?ppName?:?postProcessorNames)?{??????????????????????if?(!processedBeans.contains(ppName))?{??????????????????????????BeanDefinitionRegistryPostProcessor?pp?=?beanFactory.getBean(ppName,?BeanDefinitionRegistryPostProcessor.class);??????????????????????????registryPostProcessors.add(pp);??????????????????????????processedBeans.add(ppName);??????????????????????????pp.postProcessBeanDefinitionRegistry(registry);??????????????????????????reiterate?=?true;??????????????????????}??????????????????}??????????????}????????????????//?Now,?invoke?the?postProcessBeanFactory?callback?of?all?processors?handled?so?far?執行后處理器??????????????invokeBeanFactoryPostProcessors(registryPostProcessors,?beanFactory);??????????????invokeBeanFactoryPostProcessors(regularPostProcessors,?beanFactory);??????????}??
?
?
[html]?view plain?copy
String[]?postProcessorNames?=?beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class,?true,?false);??
按照bean的類型獲取類型為BeanDefinitionRegistryPostProcessor的bean,這里獲取到的bean名稱為:
?
org.springframework.context.annotation.internalConfigurationAnnotationProcessor;對應的Class為ConfigurationClassPostProcessor
在前面文章中創建上下文的時候beanfactory創建了該bean。
經過排序后執行如下方法
?
[html]?view plain?copy
invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors,?registry);??
?
?
[html]?view plain?copy
private?static?void?invokeBeanDefinitionRegistryPostProcessors(??????????????Collection<??extends?BeanDefinitionRegistryPostProcessor>?postProcessors,?BeanDefinitionRegistry?registry)?{????????????for?(BeanDefinitionRegistryPostProcessor?postProcessor?:?postProcessors)?{??????????????postProcessor.postProcessBeanDefinitionRegistry(registry);??????????}??????}??
實際調用ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
?
?
[html]?view plain?copy
public?void?postProcessBeanDefinitionRegistry(BeanDefinitionRegistry?registry)?{??????????...//注冊若干bean??????????processConfigBeanDefinitions(registry);??????}??
processConfigBeanDefinitions(registry)如下:
?
?
[html]?view plain?copy
public?void?processConfigBeanDefinitions(BeanDefinitionRegistry?registry)?{??????????Set<BeanDefinitionHolder>?configCandidates?=?new?LinkedHashSet<BeanDefinitionHolder>();??????????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;??????????}????????????//?Detect?any?custom?bean?name?generation?strategy?supplied?through?the?enclosing?application?context??????????SingletonBeanRegistry?singletonRegistry?=?null;??????????if?(registry?instanceof?SingletonBeanRegistry)?{??????????????singletonRegistry?=?(SingletonBeanRegistry)?registry;??????????????if?(!this.localBeanNameGeneratorSet?&&?singletonRegistry.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR))?{??????????????????BeanNameGenerator?generator?=?(BeanNameGenerator)?singletonRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);??????????????????this.componentScanBeanNameGenerator?=?generator;??????????????????this.importBeanNameGenerator?=?generator;??????????????}??????????}????????????//?Parse?each?@Configuration?class??????????ConfigurationClassParser?parser?=?new?ConfigurationClassParser(??????????????????this.metadataReaderFactory,?this.problemReporter,?this.environment,??????????????????this.resourceLoader,?this.componentScanBeanNameGenerator,?registry);????????????Set<ConfigurationClass>?alreadyParsed?=?new?HashSet<ConfigurationClass>(configCandidates.size());??????????do?{??????????????parser.parse(configCandidates);??????????????parser.validate();????????????????Set<ConfigurationClass>?configClasses?=?new?LinkedHashSet<ConfigurationClass>(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.problemReporter,?this.metadataReaderFactory,?this.resourceLoader,?this.environment,??????????????????????????this.importBeanNameGenerator,?parser.getImportRegistry());??????????????}??????????????this.reader.loadBeanDefinitions(configClasses);??????????????alreadyParsed.addAll(configClasses);????????????????configCandidates.clear();??????????????if?(registry.getBeanDefinitionCount()?>?candidateNames.length)?{??????????????????String[]?newCandidateNames?=?registry.getBeanDefinitionNames();??????????????????Set<String>?oldCandidateNames?=?new?HashSet<String>(Arrays.asList(candidateNames));??????????????????Set<String>?alreadyParsedClasses?=?new?HashSet<String>();??????????????????for?(ConfigurationClass?configurationClass?:?alreadyParsed)?{??????????????????????alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());??????????????????}??????????????????for?(String?candidateName?:?newCandidateNames)?{??????????????????????if?(!oldCandidateNames.contains(candidateName))?{??????????????????????????BeanDefinition?beanDef?=?registry.getBeanDefinition(candidateName);??????????????????????????if?(ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef,?this.metadataReaderFactory)?&&??????????????????????????????????!alreadyParsedClasses.contains(beanDef.getBeanClassName()))?{??????????????????????????????configCandidates.add(new?BeanDefinitionHolder(beanDef,?candidateName));??????????????????????????}??????????????????????}??????????????????}??????????????????candidateNames?=?newCandidateNames;??????????????}??????????}??????????while?(!configCandidates.isEmpty());????????????//?Register?the?ImportRegistry?as?a?bean?in?order?to?support?ImportAware?@Configuration?classes??????????if?(singletonRegistry?!=?null)?{??????????????if?(!singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME))?{??????????????????singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME,?parser.getImportRegistry());??????????????}??????????}????????????if?(this.metadataReaderFactory?instanceof?CachingMetadataReaderFactory)?{??????????????((CachingMetadataReaderFactory)?this.metadataReaderFactory).clearCache();??????????}??????}??
又是一段很長的代碼
?
?
[html]?view plain?copy
String[]?candidateNames?=?registry.getBeanDefinitionNames();??
獲取已經注冊的bean名稱,其信息為:
?
這里看到上一篇中創建的Application對應bean
?
[html]?view plain?copy
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));??????????????}??????????}??
判斷對應bean是否為配置文件bean(包含Configuration注解),經過篩選只有Application對應bean滿足條件
?
?
[html]?view plain?copy
ConfigurationClassParser?parser?=?new?ConfigurationClassParser(??????????????this.metadataReaderFactory,?this.problemReporter,?this.environment,??????????????this.resourceLoader,?this.componentScanBeanNameGenerator,?registry);??
該代碼構造了Configuration類解析器
?
執行
?
[html]?view plain?copy
parser.parse(configCandidates);??
?
[html]?view plain?copy
public?void?parse(Set<BeanDefinitionHolder>?configCandidates)?{??????????this.deferredImportSelectors?=?new?LinkedList<DeferredImportSelectorHolder>();????????????for?(BeanDefinitionHolder?holder?:?configCandidates)?{??????????????BeanDefinition?bd?=?holder.getBeanDefinition();??????????????try?{??????????????????if?(bd?instanceof?AnnotatedBeanDefinition)?{???//執行該部分代碼??????????????????????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());??????????????????}??????????????}??????????????catch?(BeanDefinitionStoreException?ex)?{??????????????????throw?ex;??????????????}??????????????catch?(Exception?ex)?{??????????????????throw?new?BeanDefinitionStoreException(??????????????????????????"Failed?to?parse?configuration?class?["?+?bd.getBeanClassName()?+?"]",?ex);??????????????}??????????}????????????processDeferredImportSelectors();??????}??
調用
?
?
[html]?view plain?copy
parse(((AnnotatedBeanDefinition)?bd).getMetadata(),?holder.getBeanName());??
最終調用
?
?
[html]?view plain?copy
protected?void?processConfigurationClass(ConfigurationClass?configClass)?throws?IOException?{??????????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);??????????????????for?(Iterator<ConfigurationClass>?it?=?this.knownSuperclasses.values().iterator();?it.hasNext();?)?{??????????????????????if?(configClass.equals(it.next()))?{??????????????????????????it.remove();??????????????????????}??????????????????}??????????????}??????????}????????????//?Recursively?process?the?configuration?class?and?its?superclass?hierarchy.??????????SourceClass?sourceClass?=?asSourceClass(configClass);??????????do?{??????????????sourceClass?=?doProcessConfigurationClass(configClass,?sourceClass);??????????}??????????while?(sourceClass?!=?null);????????????this.configurationClasses.put(configClass,?configClass);??????}??
首先判斷該bean是否被跳過(該部分代碼上一篇已說明),然后對Class進行包裝,調用sourceClass?= doProcessConfigurationClass(configClass,sourceClass)處理Application類
?
解析Configuration注解
?
[html]?view plain?copy
protected?final?SourceClass?doProcessConfigurationClass(ConfigurationClass?configClass,?SourceClass?sourceClass)?throws?IOException?{??????????//?Recursively?process?any?member?(nested)?classes?first??????????processMemberClasses(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.warn("Ignoring?@PropertySource?annotation?on?["?+?sourceClass.getMetadata().getClassName()?+??????????????????????????"].?Reason:?Environment?must?implement?ConfigurableEnvironment");??????????????}??????????}????????????//?Process?any?@ComponentScan?annotations??????????AnnotationAttributes?componentScan?=?AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),?ComponentScan.class);??????????if?(componentScan?!=?null?&&?!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),?ConfigurationPhase.REGISTER_BEAN))?{??????????????//?The?config?class?is?annotated?with?@ComponentScan?->?perform?the?scan?immediately??????????????Set<BeanDefinitionHolder>?scannedBeanDefinitions?=??????????????????????this.componentScanParser.parse(componentScan,?sourceClass.getMetadata().getClassName());??????????????//?Check?the?set?of?scanned?definitions?for?any?further?config?classes?and?parse?recursively?if?necessary??????????????for?(BeanDefinitionHolder?holder?:?scannedBeanDefinitions)?{??????????????????if?(ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(),?this.metadataReaderFactory))?{??????????????????????parse(holder.getBeanDefinition().getBeanClassName(),?holder.getBeanName());??????????????????}??????????????}??????????}????????????//?Process?any?@Import?annotations??????????processImports(configClass,?sourceClass,?getImports(sourceClass),?true);????????????//?Process?any?@ImportResource?annotations??????????if?(sourceClass.getMetadata().isAnnotated(ImportResource.class.getName()))?{??????????????AnnotationAttributes?importResource?=?AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),?ImportResource.class);??????????????String[]?resources?=?importResource.getStringArray("value");??????????????Class<??extends?BeanDefinitionReader>?readerClass?=?importResource.getClass("reader");??????????????for?(String?resource?:?resources)?{??????????????????String?resolvedResource?=?this.environment.resolveRequiredPlaceholders(resource);??????????????????configClass.addImportedResource(resolvedResource,?readerClass);??????????????}??????????}????????????//?Process?individual?@Bean?methods??????????Set<MethodMetadata>?beanMethods?=?sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());??????????for?(MethodMetadata?methodMetadata?:?beanMethods)?{??????????????configClass.addBeanMethod(new?BeanMethod(methodMetadata,?configClass));??????????}????????????//?Process?superclass,?if?any??????????if?(sourceClass.getMetadata().hasSuperClass())?{??????????????String?superclass?=?sourceClass.getMetadata().getSuperClassName();??????????????if?(!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;??????}??
到這里就看到了如何去解析Application類
?
?
[html]?view plain?copy
processMemberClasses(configClass,?sourceClass);??
處理其中內部類,解析內部類的過程和外部類相似,因此繼續看下面的代碼
?
處理PropertySource注解
?
[html]?view plain?copy
//?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.warn("Ignoring?@PropertySource?annotation?on?["?+?sourceClass.getMetadata().getClassName()?+??????????????????????????"].?Reason:?Environment?must?implement?ConfigurableEnvironment");??????????????}??????????}<pre?name="code"?class="html">??
[html]?view plain?copy
??
?
?
?
?
其核心操作:
?
[html]?view plain?copy
private?void?processPropertySource(AnnotationAttributes?propertySource)?throws?IOException?{??????????String?name?=?propertySource.getString("name");??????????String[]?locations?=?propertySource.getStringArray("value");??????????boolean?ignoreResourceNotFound?=?propertySource.getBoolean("ignoreResourceNotFound");??????????Assert.isTrue(locations.length?>?0,?"At?least?one?@PropertySource(value)?location?is?required");??????????for?(String?location?:?locations)?{??????????????try?{??????????????????String?resolvedLocation?=?this.environment.resolveRequiredPlaceholders(location);??????????????????Resource?resource?=?this.resourceLoader.getResource(resolvedLocation);??????????????????ResourcePropertySource?rps?=?(StringUtils.hasText(name)????????????????????????????new?ResourcePropertySource(name,?resource)?:?new?ResourcePropertySource(resource));??????????????????addPropertySource(rps);??????????????}??????????????catch?(IllegalArgumentException?ex)?{??????????????????//?from?resolveRequiredPlaceholders??????????????????if?(!ignoreResourceNotFound)?{??????????????????????throw?ex;??????????????????}??????????????}??????????????catch?(FileNotFoundException?ex)?{??????????????????//?from?ResourcePropertySource?constructor??????????????????if?(!ignoreResourceNotFound)?{??????????????????????throw?ex;??????????????????}??????????????}??????????}??????}??
通過注解中的信息獲取資源信息,然后添加到MutablePropertySourcespropertySources?= ((ConfigurableEnvironment)this.environment).getPropertySources()中,該內容前面已有講述
?
解析ComponentScan注解
?
[html]?view plain?copy
//?Process?any?@ComponentScan?annotations??????????AnnotationAttributes?componentScan?=?AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),?ComponentScan.class);??????????if?(componentScan?!=?null?&&?!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(),?ConfigurationPhase.REGISTER_BEAN))?{??????????????//?The?config?class?is?annotated?with?@ComponentScan?->?perform?the?scan?immediately??????????????Set<BeanDefinitionHolder>?scannedBeanDefinitions?=??????????????????????this.componentScanParser.parse(componentScan,?sourceClass.getMetadata().getClassName());??????????????//?Check?the?set?of?scanned?definitions?for?any?further?config?classes?and?parse?recursively?if?necessary??????????????for?(BeanDefinitionHolder?holder?:?scannedBeanDefinitions)?{??????????????????if?(ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(),?this.metadataReaderFactory))?{??????????????????????parse(holder.getBeanDefinition().getBeanClassName(),?holder.getBeanName());??????????????????}??????????????}??????????}??
ComponentScan注解的作用大家都明白,掃描執行路徑下bean信息,那么具體是如何實現的?需要跟進去看代碼,調用
?
?
[html]?view plain?copy
Set<BeanDefinitionHolder>?scannedBeanDefinitions?=??????????????????????this.componentScanParser.parse(componentScan,?sourceClass.getMetadata().getClassName());??
?
[html]?view plain?copy
public?Set<BeanDefinitionHolder>?parse(AnnotationAttributes?componentScan,?final?String?declaringClass)?{???????????...//通過注解中的信息設置掃描器的參數信息??????????return?scanner.doScan(StringUtils.toStringArray(basePackages));??????}??
代碼中忽略了掃描器對應的參數信息,直接看doScan方法
?
?
[html]?view plain?copy
protected?Set<BeanDefinitionHolder>?doScan(String...?basePackages)?{??????Assert.notEmpty(basePackages,?"At?least?one?base?package?must?be?specified");??????Set<BeanDefinitionHolder>?beanDefinitions?=?new?LinkedHashSet<BeanDefinitionHolder>();??????for?(String?basePackage?:?basePackages)?{??????????Set<BeanDefinition>?candidates?=?findCandidateComponents(basePackage);??????????for?(BeanDefinition?candidate?:?candidates)?{??????????????ScopeMetadata?scopeMetadata?=?this.scopeMetadataResolver.resolveScopeMetadata(candidate);??????????????candidate.setScope(scopeMetadata.getScopeName());??????????????String?beanName?=?this.beanNameGenerator.generateBeanName(candidate,?this.registry);??????????????if?(candidate?instanceof?AbstractBeanDefinition)?{??????????????????postProcessBeanDefinition((AbstractBeanDefinition)?candidate,?beanName);??????????????}??????????????if?(candidate?instanceof?AnnotatedBeanDefinition)?{??????????????????AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)?candidate);??????????????}??????????????if?(checkCandidate(beanName,?candidate))?{??????????????????BeanDefinitionHolder?definitionHolder?=?new?BeanDefinitionHolder(candidate,?beanName);??????????????????definitionHolder?=?AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,?definitionHolder,?this.registry);??????????????????beanDefinitions.add(definitionHolder);??????????????????registerBeanDefinition(definitionHolder,?this.registry);??????????????}??????????}??????}??????return?beanDefinitions;??}??
遍歷basePackages信息,
[html]?view plain?copy
Set<BeanDefinition>?candidates?=?findCandidateComponents(basePackage);??
查詢類路徑下申明的組件信息,
[html]?view plain?copy
public?Set<BeanDefinition>?findCandidateComponents(String?basePackage)?{??????????Set<BeanDefinition>?candidates?=?new?LinkedHashSet<BeanDefinition>();??????????try?{??????????????String?packageSearchPath?=?ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX?+??????????????????????resolveBasePackage(basePackage)?+?"/"?+?this.resourcePattern;??????????????Resource[]?resources?=?this.resourcePatternResolver.getResources(packageSearchPath);??????????????boolean?traceEnabled?=?logger.isTraceEnabled();??????????????boolean?debugEnabled?=?logger.isDebugEnabled();??????????????for?(Resource?resource?:?resources)?{??????????????????if?(traceEnabled)?{??????????????????????logger.trace("Scanning?"?+?resource);??????????????????}??????????????????if?(resource.isReadable())?{??????????????????????try?{??????????????????????????MetadataReader?metadataReader?=?this.metadataReaderFactory.getMetadataReader(resource);??????????????????????????if?(isCandidateComponent(metadataReader))?{??????????????????????????????ScannedGenericBeanDefinition?sbd?=?new?ScannedGenericBeanDefinition(metadataReader);??????????????????????????????sbd.setResource(resource);??????????????????????????????sbd.setSource(resource);??????????????????????????????if?(isCandidateComponent(sbd))?{??????????????????????????????????if?(debugEnabled)?{??????????????????????????????????????logger.debug("Identified?candidate?component?class:?"?+?resource);??????????????????????????????????}??????????????????????????????????candidates.add(sbd);??????????????????????????????}??????????????????????????????else?{??????????????????????????????????if?(debugEnabled)?{??????????????????????????????????????logger.debug("Ignored?because?not?a?concrete?top-level?class:?"?+?resource);??????????????????????????????????}??????????????????????????????}??????????????????????????}??????????????????????????else?{??????????????????????????????if?(traceEnabled)?{??????????????????????????????????logger.trace("Ignored?because?not?matching?any?filter:?"?+?resource);??????????????????????????????}??????????????????????????}??????????????????????}??????????????????????catch?(Throwable?ex)?{??????????????????????????throw?new?BeanDefinitionStoreException(??????????????????????????????????"Failed?to?read?candidate?component?class:?"?+?resource,?ex);??????????????????????}??????????????????}??????????????????else?{??????????????????????if?(traceEnabled)?{??????????????????????????logger.trace("Ignored?because?not?readable:?"?+?resource);??????????????????????}??????????????????}??????????????}??????????}??????????catch?(IOException?ex)?{??????????????throw?new?BeanDefinitionStoreException("I/O?failure?during?classpath?scanning",?ex);??????????}??????????return?candidates;??????}??
?
?
看
[html]?view plain?copy
Resource[]?resources?=?this.resourcePatternResolver.getResources(packageSearchPath);??
?
?
?
[html]?view plain?copy
public?Resource[]?getResources(String?locationPattern)?throws?IOException?{??????????Assert.notNull(locationPattern,?"Location?pattern?must?not?be?null");??????????if?(locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX))?{??????????????//?a?class?path?resource?(multiple?resources?for?same?name?possible)??????????????if?(getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length())))?{??????????????????//?a?class?path?resource?pattern??????????????????return?findPathMatchingResources(locationPattern);??????????????}??????????????else?{??????????????????//?all?class?path?resources?with?the?given?name??????????????????return?findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));??????????????}??????????}??????????else?{??????????????//?Only?look?for?a?pattern?after?a?prefix?here??????????????//?(to?not?get?fooled?by?a?pattern?symbol?in?a?strange?prefix).??????????????int?prefixEnd?=?locationPattern.indexOf(":")?+?1;??????????????if?(getPathMatcher().isPattern(locationPattern.substring(prefixEnd)))?{??????????????????//?a?file?pattern??????????????????return?findPathMatchingResources(locationPattern);??????????????}??????????????else?{??????????????????//?a?single?resource?with?the?given?name??????????????????return?new?Resource[]?{getResourceLoader().getResource(locationPattern)};??????????????}??????????}??????}??
?
?
解析路徑信息,這里spring有自己的一套繼續規則,通過findPathMatchingResources()檢索到指定類路徑下所有的*.class文件,然后調用findAllClassPathResources解析Class文件
?
[html]?view plain?copy
protected?Resource[]?findAllClassPathResources(String?location)?throws?IOException?{??????????String?path?=?location;??????????if?(path.startsWith("/"))?{??????????????path?=?path.substring(1);??????????}??????????Set<Resource>?result?=?doFindAllClassPathResources(path);??????????return?result.toArray(new?Resource[result.size()]);??????}??
?
[html]?view plain?copy
protected?Set<Resource>?doFindAllClassPathResources(String?path)?throws?IOException?{??????????Set<Resource>?result?=?new?LinkedHashSet<Resource>(16);??????????ClassLoader?cl?=?getClassLoader();??????????Enumeration<URL>?resourceUrls?=?(cl?!=?null???cl.getResources(path)?:?ClassLoader.getSystemResources(path));??????????while?(resourceUrls.hasMoreElements())?{??????????????URL?url?=?resourceUrls.nextElement();??????????????result.add(convertClassLoaderURL(url));??????????}??????????if?("".equals(path))?{??????????????//?The?above?result?is?likely?to?be?incomplete,?i.e.?only?containing?file?system?references.??????????????//?We?need?to?have?pointers?to?each?of?the?jar?files?on?the?classpath?as?well...??????????????addAllClassLoaderJarRoots(cl,?result);??????????}??????????return?result;??????}??
通過上面的代碼可以發現,在獲取到path路徑以后spring采用類加載器獲取指定Class文件對應的資源信息
?
?
獲取完資源信息后調用
?
[html]?view plain?copy
MetadataReader?metadataReader?=?this.metadataReaderFactory.getMetadataReader(resource);??
解析資源信息對應的元數據
?
?
?
[html]?view plain?copy
if?(isCandidateComponent(metadataReader))?{??????????????????????????????ScannedGenericBeanDefinition?sbd?=?new?ScannedGenericBeanDefinition(metadataReader);??????????????????????????????sbd.setResource(resource);??????????????????????????????sbd.setSource(resource);??????????????????????????????if?(isCandidateComponent(sbd))?{??????????????????????????????????if?(debugEnabled)?{??????????????????????????????????????logger.debug("Identified?candidate?component?class:?"?+?resource);??????????????????????????????????}??????????????????????????????????candidates.add(sbd);??????????????????????????????}??????????????????????????????else?{??????????????????????????????????if?(debugEnabled)?{??????????????????????????????????????logger.debug("Ignored?because?not?a?concrete?top-level?class:?"?+?resource);??????????????????????????????????}??????????????????????????????}??????????????????????????}??????????????????????????else?{??????????????????????????????if?(traceEnabled)?{??????????????????????????????????logger.trace("Ignored?because?not?matching?any?filter:?"?+?resource);??????????????????????????????}??????????????????????????}??
如果存在Componment注解修飾的Class文件則加入到BeanDefinition集合中返回。
?
?
回到調用掃描bean處
?
[html]?view plain?copy
for?(BeanDefinitionHolder?holder?:?scannedBeanDefinitions)?{??????????????????if?(ConfigurationClassUtils.checkConfigurationClassCandidate(holder.getBeanDefinition(),?this.metadataReaderFactory))?{??????????????????????parse(holder.getBeanDefinition().getBeanClassName(),?holder.getBeanName());??????????????????}??????????????}??
遍歷掃描到的bean信息,如果為配置bean,則執行parse方法,該方法調用processConfigurationClass,形成一個遞歸的操作。
?
解析Import注解
?
[html]?view plain?copy
processImports(configClass,?sourceClass,?getImports(sourceClass),?true);
?
處理import注解,該注解在spring boot中使用非常頻繁
?
[html]?view plain?copy
private?void?processImports(ConfigurationClass?configClass,?SourceClass?currentSourceClass,??????????????Collection<SourceClass>?importCandidates,?boolean?checkForCircularImports)?throws?IOException?{?????????????...?????????????????????????this.importStack.push(configClass);??????????????try?{??????????????????for?(SourceClass?candidate?:?importCandidates)?{??????????????????????if?(candidate.isAssignable(ImportSelector.class))?{??????????????????????????//?Candidate?class?is?an?ImportSelector?->?delegate?to?it?to?determine?imports??????????????????????????Class<?>?candidateClass?=?candidate.loadClass();??????????????????????????ImportSelector?selector?=?BeanUtils.instantiateClass(candidateClass,?ImportSelector.class);??????????????????????????invokeAwareMethods(selector);??????????????????????????if?(this.deferredImportSelectors?!=?null?&&?selector?instanceof?DeferredImportSelector)?{??????????????????????????????this.deferredImportSelectors.add(??????????????????????????????????????new?DeferredImportSelectorHolder(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))?{??????????????????????????//?Candidate?class?is?an?ImportBeanDefinitionRegistrar?->??????????????????????????//?delegate?to?it?to?register?additional?bean?definitions??????????????????????????Class<?>?candidateClass?=?candidate.loadClass();??????????????????????????ImportBeanDefinitionRegistrar?registrar?=??????????????????????????????????BeanUtils.instantiateClass(candidateClass,?ImportBeanDefinitionRegistrar.class);??????????????????????????invokeAwareMethods(registrar);??????????????????????????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?(Exception?ex)?{??????????????????throw?new?BeanDefinitionStoreException("Failed?to?process?import?candidates?for?configuration?class?["?+??????????????????????????configClass.getMetadata().getClassName()?+?"]",?ex);??????????????}??????????????finally?{??????????????????this.importStack.pop();??????????????}??????????}??????}??
如果Import注解中Class為ImportSelector子類,通過invokeAwareMethods(selector)設置aware值,如果類型為DeferredImportSelector則添加到deferredImportSelectors集合中,待前面的parser.parse(configCandidates)
?
方法中processDeferredImportSelectors()處理;如果不是,則執行selectImports方法,將獲取到的結果遞歸調用processImports,解析selectImports得到的結果
如果Import注解中Class為ImportBeanDefinitionRegistrar子類,則添加到importBeanDefinitionRegistrars中,注意該部分的數據在執行完parser.parse(configCandidates)后調用this.reader.loadBeanDefinitions(configClasses)解析
否則執行配置信息的解析操作。
?
解析ImportResource注解
?
[html]?view plain?copy
//?Process?any?@ImportResource?annotations??????????if?(sourceClass.getMetadata().isAnnotated(ImportResource.class.getName()))?{??????????????AnnotationAttributes?importResource?=?AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(),?ImportResource.class);??????????????String[]?resources?=?importResource.getStringArray("value");??????????????Class<??extends?BeanDefinitionReader>?readerClass?=?importResource.getClass("reader");??????????????for?(String?resource?:?resources)?{??????????????????String?resolvedResource?=?this.environment.resolveRequiredPlaceholders(resource);??????????????????configClass.addImportedResource(resolvedResource,?readerClass);??????????????}??????????}??
?
?
解析Bean注解
?
[html]?view plain?copy
Set<MethodMetadata>?beanMethods?=?sourceClass.getMetadata().getAnnotatedMethods(Bean.class.getName());??????????for?(MethodMetadata?methodMetadata?:?beanMethods)?{??????????????configClass.addBeanMethod(new?BeanMethod(methodMetadata,?configClass));??????????}??
?
?
上面這兩個注解相對來講要簡單一些,至此bean的解析完成,這里面涉及到多重遞歸,首先理清楚一條線才能把代碼看明白。
總結
以上是生活随笔為你收集整理的spring boot实战(第十篇)Spring boot Bean加载源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。