一、IoC容器中建立BeanDefinition数据映射
主要有三步:
1.BeanDefinition的Resource定位
2.BeanDefinition的载入
3.注册BeanDefinition
下面逐步分析
二、BeanDefinition的Resource定位
过程由ResourceLoader通过统一的Resource接口完成
三种常规定位方式:
1.主类所在包,@Component和@ComponentScan定位资源
@Component标明哪个类被扫描进入Spring IoC容器
@ComponentScan标明采用何种策略去扫描装配Bean
2.SPI扩展机制实现的自动装配(比如各种starter)
3.@Import注解指定的类
4.引入XML配置Bean:xml文件+@ImportResource,通过它可以引入对应的XML文件
三、BeanDefinition的载入
把用户定义好的Bean表示成IoC容器内部的数据结构BeanDefinition
下面主要介绍@ComponentScan注解引入的方式:
1.通过主类找到了basePackage
2.AnnotationScopeMetadataResolver类会将该路径下所有的.class文件都加载进来
遍历判断是不是有@Component注解,如果有,就是要装载的BeanDefinition
注:@Configuration,@Controller,@Service等注解底层都是@Component注解,只不过包装了一层
四、注册BeanDefinition
通过BeanDefinitionRegister接口的registerBeanDefinition()方法来完成
在IoC容器中将BeanDefinition注入到DefaultListableBeanFactory的beanDefinitionMap属性(一个ConcurrentHashMap)中
五、源码分析
入囗:
AbstractApplicationContext抽象类的refresh()方法中的
invokeBeanFactoryPostProcessors(beanFactory)
方法
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory)
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME))
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
其中核心代码是PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
方法代码很长,说下其主要逻辑:
加载容器中所有BeanFactoryPostProcessor的实现类,执行其postProcessBeanFactory()方法,
如果这些实现类也实现了BeanDefinitionRegistryPostProcessor接囗,执行其postProcessBeanDefinitionRegistry()方法
因为postProcessBeanFactory()中会加载BeanDefinition,而这个BeanDefinition可能也是BeanFactoryPostProcessor的实现类,所以方法中用了几重遍历
过程中会加载ConfigurationClassPostProcessor
类,这个类会解析加了@ComponentScan和@ComponentScans扫描出的Bean,将这些Bean封装成BeanDefinition,并放入DefaultListableBeanFactory的beanDefinitionMap属性一个ConcurrentHashMap)中
下面具体分析此类:
其postProcessBeanDefinitionRegistry()
方法中
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
int registryId = System.identityHashCode(registry);
if (this.registriesPostProcessed.contains(registryId))
throw new IllegalStateException(
"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
if (this.factoriesPostProcessed.contains(registryId))
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + registry);
this.registriesPostProcessed.add(registryId);
processConfigBeanDefinitions(registry);
重点看processConfigBeanDefinitions(registry)
方法
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry)
List<BeanDefinitionHolder> configCandidates = new ArrayList<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;
// Sort by previously determined @Order value, if applicable
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>()
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2)
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
);
// 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 && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR))
BeanNameGenerator generator = (BeanNameGenerator) sbr.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<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do
parser.parse(candidates);
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.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
this.reader.loadBeanDefinitions(configClasses);
alreadyParsed.addAll(configClasses);
candidates.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 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)
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME))
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory)
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
方法内容如下:
1.checkConfigurationClassCandidate():
判断类是否是一个配置类,并为BeanDefinition设置属性为lite或者full
@Configuration,对应的BeanDefinition为full
@Bean,@Component,@ComponentScan,@Import,@ImportResource,对应的BeanDefinition为lite
2.parser.pase()->ConfigurationClassParser.parse():
解析配置类
解析配置类上的注解(ComponentScan扫描出的类,@Import注册的类,以及@Bean方法定义的类),
将解析结果放入到parser的configurationClasses属性中(一个Map)
3. this.reader.loadBeanDefinitions():
将通过@Import、@Bean等注解方式注册的类解析成BeanDefinition,然后注册到BeanDefinitionMap中,
如果bean上存在@Import注解,且import的类实现了ImportBeanDefinitionRegistrar接口,执行类的registerBeanDefinitions()方法
其中最重要的第2步,使用了ConfigurationClassParser的parse()方法
:
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 (Throwable ex)
throw new BeanDefinitionStoreException(
"Failed to parse configuration class " + bd.getBeanClassName() + "", ex);
processDeferredImportSelectors();
会调用到parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName())
;
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);
}
方法内容如下:
1.SourceClass sourceClass = asSourceClass(configClass, filter);
递归地处理配置类及其父类层次结构
2.doProcessConfigurationClass(configClass, sourceClass, filter):
递归处理Bean,如果有父类,递归处理,直到顶层父类
核心是doProcessConfigurationClass()方法
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
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
// The config class is annotated with @ComponentScan -> perform the scan immediately
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 needed
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("locations");
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 = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
// Process default methods on interfaces
processInterfaces(configClass, sourceClass);
// Process superclass, if any
if (sourceClass.getMetadata().hasSuperClass()) {
String superclass = sourceClass.getMetadata().getSuperClassName();
if (!superclass.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;
}
方法内容如下:
1.解析内部类:
配置类上有@Configuration注解,该注解继承 @Component,
if 判断为true,调用processMemberClasses方法,递归解析配置类中的内部类
2.解析@PropertySource:
如果配置类上有@PropertySource注解,则解析加载properties文件,并将属性添加到Spring上下文中
3.处理@ComponentScan注解:
1.获取配置类上的@ComponentScan注解
2.循环所有的ComponentScan,立即执行扫描:
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName())
3.检验获得的BeanDefinition中是否有配置类:
有@Configuration、@Component、@ComponentScan、@Import、@ImportResource和@Bean中的其中一个注解,
递归调用parse方法,进行解析
4.解析@Import注解,并加载该注解指定的配置类:
SpringBoot项目中经常用的各种@Enable*** 注解基本都是封装的@Import
processImports(configClass, sourceClass, getImports(sourceClass), true)
5.解析@ImportResource:
以导入xml配置文件
6.解析@Bean methods:
将@Bean方法转化为BeanMethod对象,添加到ConfigurationClass#beanMethods集合中
核心是3.2ComponentScanAnnotationParser#parse()方法
public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
Assert.state(this.environment != null, "Environment must not be null");
Assert.state(this.resourceLoader != null, "ResourceLoader must not be null");
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
BeanUtils.instantiateClass(generatorClass));
ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
scanner.setScopedProxyMode(scopedProxyMode);
}
else {
Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
}
scanner.setResourcePattern(componentScan.getString("resourcePattern"));
for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addIncludeFilter(typeFilter);
}
}
for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
for (TypeFilter typeFilter : typeFiltersFor(filter)) {
scanner.addExcludeFilter(typeFilter);
}
}
boolean lazyInit = componentScan.getBoolean("lazyInit");
if (lazyInit) {
scanner.getBeanDefinitionDefaults().setLazyInit(true);
}
Set<String> basePackages = new LinkedHashSet<String>();
String[] basePackagesArray = componentScan.getStringArray("basePackages");
for (String pkg : basePackagesArray) {
String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
basePackages.addAll(Arrays.asList(tokenized));
}
for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
basePackages.add(ClassUtils.getPackageName(clazz));
}
if (basePackages.isEmpty()) {
basePackages.add(ClassUtils.getPackageName(declaringClass));
}
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
@Override
protected boolean matchClassName(String className) {
return declaringClass.equals(className);
}
});
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
方法内容如下:
1.创建一个ClassPathBeanDefinitionScanner对象:
new ClassPathBeanDefinitionScanner()
2.扫描并注册BeanDefinition:
scanner.doScan(StringUtils.toStringArray(basePackages)):,
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;
}
registerBeanDefinition(definitionHolder, this.registry)方法:
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
方法内容如下:
1.从指定的包中扫描需要装载的Bean:
Set candidates = findCandidateComponents(basePackage)
2.将该Bean注册进IoC容器(beanDefinitionMap):
registerBeanDefinition(definitionHolder, this.registry)
registerBeanDefinition(definitionHolder, registry)方法
:
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
就是BeanDefinitionRegistry#registerBeanDefinition()方法
DefaultListableBeanFactory实现了BeanDefinitionRegistry接囗,对方法进行了重写
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + oldBeanDefinition +
"] with [" + beanDefinition + "]");
}
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
核心就是this.beanDefinitionMap.put(beanName, beanDefinition);
终于结束了
开头已经总结了过程,这里总结下代码流程吧:
入囗:
AbstractApplicationContext抽象类的refresh()方法中的invokeBeanFactoryPostProcessors(beanFactory)方法
实现:
核心类ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()方法
里面的各个核心方法:
最核心:
ClassPathBeanDefinitionScanner#doScan()方法
1.从指定的包中扫描需要装载的Bean:
Set candidates = findCandidateComponents(basePackage)
2.将该Bean注册进IoC容器(beanDefinitionMap):
registerBeanDefinition(definitionHolder, this.registry)
代码太长了,想细看的话,可以照着这个核心一个个来看