PS: 查看源码的jar版本为 Spring-beans:5.2.15.release
1. 获取BeanFactory子流程
2. BeanDefinition加载解析及注册子流程
- 该子流程涉及如下几个关键步骤
- Resource定位:指对BeanDefinition的资源定位过程。通俗里说就是找到定位JavaBean信息的XML文件,并将其封装成Resource对象。
- BeanDefinition载入:把定义好的Javabean表示为IOC容器内部的数据结构,这个容器内部的数据结构就是BeanDefinition。
- 注册BeanDefinition到IOC容器
- 过程分析
Step1:子流程入口在AbstractRefreshableApplicationContext#refreshBeanFactory
(从AbstractApplicationContext#refresh#obtainFreshBeanFactory()点进来)
//加载应用中的BeanDefinitions
loadBeanDefinitions(beanFactory);
Step2:依次调⽤多个类的 loadBeanDefinitions ⽅法
—>AbstractXmlApplicationContext —>AbstractBeanDefinitionReader —>
XmlBeanDefinitionReader ⼀直执⾏到XmlBeanDefinitionReader 的 doLoadBeanDefinitions ⽅法
try {
//读取xml信息,将xml信息保存到Document对象
Document doc = doLoadDocument(inputSource, resource);
//解析document对象 封装BeanDefinition对象并进行注册
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
Step3: 我们重点观察XmlBeanDefinitionReader 类的 registerBeanDefinitions ⽅法,期间产⽣了多次重载调⽤,我们定位到最后⼀个。(XmlBeanDefinitionReader#registerBeanDefinitions)
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//获取已有BeanDefinition的数量
int countBefore = getRegistry().getBeanDefinitionCount();
//注册BeanDefinition
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//返回新注册的BeanDefinition的数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
此时我们关注两个地方:一个是createReaderContext方法 ,一个是 registerBeanDefinitions方法。
先进入createReaderContext方法看看
//1
public XmlReaderContext createReaderContext(Resource resource) {
return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
this.sourceExtractor, this, getNamespaceHandlerResolver());
}
...
//2
public NamespaceHandlerResolver getNamespaceHandlerResolver() {
if (this.namespaceHandlerResolver == null) {
this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
}
return this.namespaceHandlerResolver;
}
...
//3
protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
return new DefaultNamespaceHandlerResolver(cl);
}
我们可以看到,此处Spring首先完成了NamespaceHandlerResolver的初始化。
我们再进入registerBeanDefinitions方法中追踪,调用了DefaultBeanDefinitionDocumentReader#registerBeanDefinitionsf方法
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
doRegisterBeanDefinitions(doc.getDocumentElement());
}
进入doRegisterBeanDefinitions方法
进入parseBeanDefinitions#parseDefaultElement方法
进入processBeanDefinition方法
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//解析bean元素为BeanDefinition,但此时使用BeanDefinitionHolder又包装成了BeanDefinitionHolder对象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//如果有自定义标签则处理自定义标签
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 完成BeanDefinition的注册
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
至此,注册流程结束,我们发现,所谓的注册就是把封装的XML中定义的Bean信息封装为BeanDefinition对象之后放入一个Map中,BeanFactory是以Map的结构组织这些BeanDefinition的。
DefaultListableBeanFactory#registerBeanDefinition
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
可以在DefaultListableBeanFactory中看到此Map的定义
/** Map of bean definition objects, keyed by bean name. */
private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);
-
时序图
时序图