接著上一篇文章將 refresh方法
首先看一下測試項(xiàng)目代碼
主類,將Myconfiguration.class注入進(jìn)ApplictionContext

配置類

Car類實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口

MySpringBean標(biāo)注了@Component

看一下refresh方法,(AbstractApplicationContext#refresh)
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// AnnotationConfigApplicationContext因?yàn)槔^承 GenericApplicationContext
//點(diǎn)進(jìn)obtainFreshBeanFactory()方法,發(fā)現(xiàn)beanFactory是DefaultListableBeanFactory();
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");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// 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) {
if (logger.isWarnEnabled()) {
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;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
contextRefresh.end();
}
}
}
這里就是spring里關(guān)于bean的核心方法,筆者并沒有全部看過,這里也介紹bean的主線代碼,繼續(xù)分析
AbstractApplicationContext#invokeBeanFactoryPostProcessors方法,
這里就涉及到最重要的類ConfigurationClassPostProcess,首先看一下繼承關(guān)系,實(shí)現(xiàn)了
BeanDefinitionRegistryPostProcessor(postProcessBeanDefinitionRegistry)和
BeanFactoryPostProcessor(postProcessBeanFactory),后續(xù)對調(diào)用這兩個(gè)方法


PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors方法中
主要作用就是通過實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor 接口類(一般指的是ConfigurationClassPostProcessor類)的postProcessBeanDefinitionRegistry方法掃面項(xiàng)目,將需要的類(比如@service @controller @configuration注解標(biāo)注的類)加入到beanDefinitionMap中,并調(diào)用實(shí)現(xiàn)BeanFactoryPostProcessor的類的
postProcessBeanFactory方法修改beanDefinition,
在invokeBeanFactoryPostProcessors有g(shù)etBean方法,會將bean放到一級緩存中,但是沒有賦值屬性

public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
//已經(jīng)處理過的bean,防止bean后置處理器被重復(fù)的執(zhí)行
Set<String> processedBeans = new HashSet<>();
//判斷beanFacroty是否實(shí)現(xiàn)BeanDefinitionRegistry,因?yàn)樾枰@取bean和注冊bean的功能
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// BeanFactoryPostProcessor實(shí)現(xiàn)類的集合,過濾的是入?yún)eanFactoryPostProcessors中的
// BeanFactoryPostProcessor接口的實(shí)現(xiàn)類
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// BeanDefinitionRegistryPostProcessor實(shí)現(xiàn)類的集合
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// beanFactoryPostProcessors通過AbstractApplicationContext#addBeanFactoryPostProcessor方法添加的,
//springboot在啟動的時(shí)候會調(diào)用addBeanFactoryPostProcessor方法
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
//如果手動添加的BeanDefinitionRegistry是BeanDefinitionRegistryPostProcessor的實(shí)現(xiàn)類
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//調(diào)用postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
//添加到registryProcessors中
registryProcessors.add(registryProcessor);
}
else {
//如果不是BeanDefinitionRegistryPostProcessor的實(shí)現(xiàn)類,就是BeanFactoryPostProcessor的實(shí)現(xiàn)類,添加到regularPostProcessors
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<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
//從DefaultListableBeanFactory的beanDefinitionNames成員變量中獲取//BeanDefinitionRegistryPostProcessor的bean的處理器名稱
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//過濾,只留實(shí)現(xiàn)PriorityOrdered接口的類,排序用
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//getBean獲取bean,添加到currentRegistryProcessors中,這是馬上就要處理的集合,
// getBean獲取的類是ConfigurationClassPostProcessor
//getBean的源碼后續(xù)會分析到
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//添加到processedBeans中,這是代表已經(jīng)處理的集合
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加registryProcessors集合
registryProcessors.addAll(currentRegistryProcessors);
//執(zhí)行postProcessBeanDefinitionRegistry方法,這里出現(xiàn)的一般都是
//ConfigurationClassPostProcessor ,這個(gè)類是springioc容器最重要的類
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
//清空currentRegistryProcessors,后續(xù)還會用到
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
//從DefaultListableBeanFactory的beanDefinitionNames成員變量中獲取
//BeanDefinitionRegistryPostProcessor的bean的處理器名稱,代碼和上面一樣,執(zhí)行實(shí)現(xiàn)
//Ordered接口的類,排序用
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//唯一不同的是,這里多了一個(gè)判斷條件,過濾掉已經(jīng)指定過的bean
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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
//執(zhí)行剩下的bean,因?yàn)轫?xiàng)目中創(chuàng)建了Car類并且實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor
//接口,所以這里剩下的只有car
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
// currentRegistryProcessors馬上就要處理的集合
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//已經(jīng)處理的bean,避免重復(fù)執(zhí)行
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//調(diào)用registryProcessors和regularPostProcessors的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
//如果bean工廠沒有實(shí)現(xiàn)BeanDefinitionRegistry 接口,說明沒有注冊Bean定義的能力
// 那么就直接調(diào)用BeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法
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!
//獲取BeanFactoryPostProcessor接口的實(shí)例名稱
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
//實(shí)現(xiàn)PriorityOrdered和BeanFactoryPostProcessors接口的類
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
//實(shí)現(xiàn)Ordered和BeanFactoryPostProcessors接口類名稱(beanDefinitionMap的key)
List<String> orderedPostProcessorNames = new ArrayList<>();
//沒有實(shí)現(xiàn)PriorityOrdered和Ordered接口的類名稱(beanDefinitionMap的key)
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
//已經(jīng)處理過的bean,什么也不做
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
//實(shí)現(xiàn)PriorityOrdered接口的類getBean并add進(jìn)priorityOrderedPostProcessors
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
//實(shí)現(xiàn)Ordered接口類名稱add orderedPostProcessorNames
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
//剩余類名稱的add進(jìn)nonOrderedPostProcessorNames
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//下面的代碼就是執(zhí)行BeanFactoryPostProcessor的postProcessBeanFactory方法
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(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<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(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();
}
下面兩張圖體現(xiàn)了當(dāng)調(diào)用
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法之后將car注入到beanDefinitionMap中


invokeBeanDefinitionRegistryPostProcessors方法調(diào)用類的
postProcessBeanDefinitionRegistry方法,其實(shí)就是調(diào)用
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry方法,為什么是這個(gè)類,已經(jīng)分析過了,當(dāng)調(diào)用postProcessBeanDefinitionRegistry方法的時(shí)候,最終調(diào)用的是processConfigBeanDefinitions方法,上兩張圖注意到car的注入,那car是如何通過processConfigBeanDefinitions方法,注入進(jìn)ioc容器中的
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
//從現(xiàn)有的beanDefinitionNames中獲取bean的名稱①
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
//獲取beanDefinition
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//判斷類是否被解析過,解析過的類返回不為null,這里涉及到類是完成配置類還是非完全配置類
if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//判斷類是否有@Configuration注解,如果沒有看是否標(biāo)注了@Component@ComponentScan
//@Import@ImportResource,如果還沒有則看是否包含@Bean注解的方法,以上都沒有則返回false ②
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
//執(zhí)行完下面的方法時(shí)configCandidates只有MyConfiguration配置類,
//有MyConfiguration,不是因?yàn)闃?biāo)注了@configuration注解是在new AnnotationConfigApplicationContext(Myconfiguration.class)時(shí)候,存入進(jìn)beanDefinitionMaps中的
//這里有個(gè)疑問為什么
//沒有MySpringBean呢,到現(xiàn)在為止還沒有涉及到注解,在解析MyConfiguration配置類的代碼的時(shí)候
//通過MyConfiguration類的@ComponentScan注解就會
//把MySpringBean掃描出來并放到beanDefinitionMap中,
//MyConfiguration標(biāo)注了@Configuration,不但滿足了上面的
//checkConfigurationClassCandidate條件,而且還是FULL類型的配置類
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
// Return immediately if no @Configuration classes were found
if (configCandidates.isEmpty()) {
return;
}
// Sort by previously determined @Order value, if applicable
//根據(jù)類的@Order排序,這就是我們經(jīng)常使用的,用@Order來決定類解析的順序,
//@order小的排在前面
configCandidates.sort((bd1, bd2) -> {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return Integer.compare(i1, i2);
});
// Detect any custom bean name generation strategy supplied through the enclosing application context
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
if (generator != null) {
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
}
if (this.environment == null) {
this.environment = new StandardEnvironment();
}
// Parse each @Configuration class
//創(chuàng)建解析器
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
//此時(shí)configCandidates只有MyConfiguration一個(gè)類
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
//解析配置類,當(dāng)執(zhí)行這個(gè)方法的時(shí)候,就會解析出很多類,其中就包括MySpringBean類③
parser.parse(candidates);
parser.validate();
//獲取掃描到的類,此時(shí)還沒有放到beanDefinitionMap中
Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
//去除已經(jīng)解析過的類
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());
}
//將解析出來的配置類存放到beanDefinitionMap中,④
this.reader.loadBeanDefinitions(configClasses);
//將加載的類放到alreadyParsed中
alreadyParsed.addAll(configClasses);
processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
candidates.clear();
//因?yàn)橛袙呙璧念惔娣诺絙eanDefinitionMap中,并且類中可能還有@Bean @Import等注解,所以下面一定大于
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
// candidateNames 為方法最開始定義的,里面只有spring啟動的時(shí)候存放的配置類
Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
// Clear cache in externally provided MetadataReaderFactory; this is a no-op
// for a shared cache since it'll be cleared by the ApplicationContext.
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
①解釋為什么configCandidates只有MyConfiguration配置類

②ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)
我們只關(guān)注checkConfigurationClassCandidate方法中的部分代碼
Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
//判斷是否標(biāo)注了@Configuration并且proxyBeanMethods屬性是否為false再取反即使判斷是否為true,默認(rèn)為true
if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
//定義該類為完全配置類,對于什么是完全配置類后續(xù)會分析
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
}
//判斷否標(biāo)注了@Component@ComponentScan@Import@ImportResource,如果還沒有則看是否包含@Bean注解的方法,
else if (config != null || isConfigurationCandidate(metadata)) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
}
//以上都沒有則返回false
else {
return false;
}
③ 解析到的配置類

Parse方法調(diào)用結(jié)束后,共掃描出3個(gè)類

查看parser.parse(candidates)
ConfigurationClassParser#parse(Set<BeanDefinitionHolder> configCandidates)
-->ConfigurationClassParser#processConfigurationClass
-->ConfigurationClassParser#doProcessConfigurationClass
在doProcessConfigurationClass方法中可以大概的看出
主要是看類是否包含@Component @PropertySources @ComponentScans @ImportResource注釋 如果ComponentScans注解,通過路徑還要掃描類,
提一下在spring解析的時(shí)候,如果@ComponentScans的basePackages為空的時(shí)候,掃描路徑就是當(dāng)前類所在的包,這段代碼在ComponentScanAnnotationParser的parse方法中
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
Collections.addAll(basePackages, tokenized);
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
//如果為null,使用當(dāng)前類所在的包
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
下一步呢 就是把包下所有的類都找到,并根據(jù)excludeFilters includeFilters的規(guī)則,找到標(biāo)注了@Component注解的類,這里就不分析了,關(guān)注一下
ClassPathBeanDefinitionScanner#doScan方法下的
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
basePackage就是包的掃描路徑, findCandidateComponents方法中查找包下的所有類,在遍歷,過濾出標(biāo)注了@Component注解的類

this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); 方法的第一行代碼就new ClassPathBeanDefinitionScanner,并沒有使用AnnotationConfigApplicationContext構(gòu)造方法new ClassPathBeanDefinitionScanner對象,方法里面解析了@ConfigurationScan注解的屬性,根據(jù)屬性掃描類,最后scanner.doScan(StringUtils.toStringArray(basePackages));來掃描,并判斷beanName 不能重復(fù),如果重復(fù)則拋出異常
還要介紹一下
ConfigurationClassParser# doProcessConfigurationClass的下面這段代碼
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
主要是通過@Import(ImportSelector實(shí)現(xiàn)類.class) 的selectImports導(dǎo)入的類
包裝成configClass,并賦值importBy為標(biāo)注了@import的元類
http://www.itdecent.cn/p/4223ea69eb1f 這篇文章分析過是符合導(dǎo)入的
到此為止,把所有@ConfigurationScan掃描的類和@import的類都放到configClasses中
是通過ConfigurationClassParser#processConfigurationClass
this.configurationClasses.put(configClass, configClass);
這個(gè)方法存放進(jìn)configClasses的

- ④this.reader.loadBeanDefinitions(configClasses); 將掃描的類加載進(jìn)beanDefinitionMap中,并在加載之前,掃面類中是否含有@Bean注解,如果有也將掃面進(jìn)beanDefinitionMap中
private void loadBeanDefinitionsForConfigurationClass(
ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
if (trackedConditionEvaluator.shouldSkip(configClass)) {
String beanName = configClass.getBeanName();
if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
this.registry.removeBeanDefinition(beanName);
}
this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
return;
}
//如果當(dāng)前的類是通過@Import導(dǎo)入的,是在
// ConfigurationClassParser#doProcessConfigurationClass的
//processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
//將標(biāo)注@Import獲取出來的,這段代碼就是將@Import標(biāo)注的類存放beanDefinitionMap中
if (configClass.isImported()) {
registerBeanDefinitionForImportedConfigurationClass(configClass);
}
//如果configClass中有@bean方法,也將返回類存放進(jìn)beanDefinitionMap中,key為方法名稱
for (BeanMethod beanMethod : configClass.getBeanMethods()) {
loadBeanDefinitionsForBeanMethod(beanMethod);
}
//是不是通過@ImportResources注解導(dǎo)入進(jìn)來的
loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
//是否實(shí)現(xiàn)ImportBeanDefinitionRegistrar, ImportBeanDefinitionRegistrar是擴(kuò)展接口//通過registerBeanDefinitions手動的注冊beanDefinition, 實(shí)現(xiàn)//ImportBeanDefinitionRegistrar的類都是通過@Import導(dǎo)入的,并且實(shí)現(xiàn)類本身不會注入進(jìn)//beanDefinitionMap中
loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
以上是關(guān)于ConfigruationClassPostProcessor的postProcessBeanDefinitionRegistry方法
下面介紹ConfigruationClassPostProcessor#postProcessBeanFactory方法
那我們在回到最開始說的
AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中的
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);調(diào)用的就
ConfigruationClassPostProcessor#postProcessBeanFactory方法
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
enhanceConfigurationClasses方法對Bean的增強(qiáng)
遍歷所有的beanDefinitionMap中的beanDefinition
如果類ConfigurationClassUtils.CONFIGURATION_CLASS_FULL前面提到過,就是類被@Configuration注釋了,就會被CGLIB代理,將beanDefinition中的beanClass屬性替換成被代理之后的類,
代理類的用處是什么呢,下面兩張圖可以解釋,本次分析的
AbstractApplicationContext#refresh方法的invokeBeanFactoryPostProcessors(beanFactory);代碼不會創(chuàng)建Bean,下面兩張圖不是執(zhí)行invokeBeanFactoryPostProcessors代碼時(shí)打印的


還沒有介紹@Conditional的注解的使用,
this.reader.loadBeanDefinitions(configClasses)執(zhí)行這個(gè)方法的時(shí)候,會解析@Conditional的一系列注解,springboot 中使用的是SpringBootCondition#matches方法,
ConditionOutcome outcome = getMatchOutcome(context, metadata);
getMatchOutcome方法是抽象方法具體的實(shí)現(xiàn),如下就是OnBeanCondition的getMatchOutcome方法
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean
總結(jié)一下
本文其實(shí)主要介紹的就是
AbstractApplicationContext#refresh方法的invokeBeanFactoryPostProcessors(beanFactory);方法
invokeBeanFactoryPostProcessors方法主要就是調(diào)用ConfigruationClassPostProcessor的postProcessBeanDefinitionRegistry方法和postProcessBeanFactory方法
postProcessBeanDefinitionRegistry方法的作用是首先通過@ComponentScans掃描標(biāo)注了@Component的類添加到beanDefinitionMap,遍歷beanDefinitionMap如果標(biāo)注@Import注解,根據(jù)selectImports返回的數(shù)組添加到configClasses中,再遍歷configClasses,把標(biāo)注@Bean @ImportSource 包裝成beanDefintion添加到beanDefinitionMap中.
postProcessBeanFactory方法標(biāo)注了@Configuration類,定義為增強(qiáng)類CGLIB代理,將beanDefinition中的beanClass屬性替換成被代理之后的類.