先总结: 该方法new了一个beanFactory, 设置了一些忽略的接口, 加载并解析了bean.xml, 主要将bean信息解析为BeanDefinition保存到beanFactory中
1.refreshBeanFactory()方法
1.1 创建DefaultListableBeanFactory对象: createBeanFactory() -> new DefaultListableBeanFactory(getInternalParentBeanFactory());
1.2 定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖: customizeBeanFactory(beanFactory);
1.3 初始化documentReader,并进行XML文件读取及解析,默认命名空间的解析,自定义标签的解析: loadBeanDefinitions(beanFactory); 注意: 解析xml核心方法
创建一个xml的beanDefinitionReader,并通过回调设置到beanFactory中:
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory)
给reader对象设置环境对象: beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
初始化beanDefinitionReader对象,此处设置配置文件是否要进行验证: initBeanDefinitionReader(beanDefinitionReader);
始完成beanDefinition的加载: loadBeanDefinitions(beanDefinitionReader);
通过XmlBeanDefinitionReader对象, 遍历加载所有xml配置文件:
loadBeanDefinitions
-> loadBeanDefinitions(new EncodedResource(resource));
-> doLoadBeanDefinitions(inputSource, encodedResource.getResource()); //xml解析核心步骤
-> Document doc = doLoadDocument(inputSource, resource); //获取xml文件的document对象
int count = registerBeanDefinitions(doc, resource); //解析document对象, 封装成一个个的BeanDefinition对象
-> BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
-> doRegisterBeanDefinitions(doc.getDocumentElement());
-> preProcessXml(root);
parseBeanDefinitions(root, this.delegate); //从根节点标签开始解析
postProcessXml(root);
-> parseDefaultElement(ele, delegate); //解析默认元素标签: <beans></beans>
delegate.parseCustomElement(ele); //解析自定义元素标签
--> 默认标签解析
if (delegate.nodeNameEquals(ele,"import")) {
importBeanDefinitionResource(ele); //处理import标签元素
}else if (delegate.nodeNameEquals(ele, "alias")) {
processAliasRegistration(ele); //处理alias标签元素
}else if (delegate.nodeNameEquals(ele,"alias")) {
processBeanDefinition(ele, delegate); //处理bean标签元素
}else if (delegate.nodeNameEquals(ele,"beans")) {
doRegisterBeanDefinitions(ele); //递归处理beans标签元素
}
---> 处理import标签元素
String location = ele.getAttribute("resource"); //获取resource属性
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location); //通过之前加载的系统环境变量替换字符串中的如: ${user.dir}的变量
boolean absoluteLocation = false;
try {
absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); //判断location是绝对URI还是相对URI, classpath*:开头的为绝对路径
}
//如果是绝对URI则直接根据地址加载对应的配置文件
getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
//如果是相对路径,则根据相对地址计算出绝对地址
getReaderContext().getReader().loadBeanDefinitions(relativeResource);
//解析后进行监听器激活处理
---> 处理alias标签元素
String name = ele.getAttribute(''name"); //获取beanName
String alias = ele.getAttribute("alias"); //获取alias
getReaderContext().getRegistry().registerAlias(name, alias); //注册alias
getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); //别名注册后通知监听器做相应处理
---> 处理bean标签元素
beanDefinitionHolder是beanDefinition对象的封装类,封装了BeanDefinition,bean的名字和别名,用它来完成向IOC容器的注册,
得到beanDefinitionHolder就意味着beandefinition是通过BeanDefinitionParserDelegate对xml元素的信息按照spring的bean规则进行解析得到
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); //向ioc容器注册解析得到的beandefinition的地方
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); //在beandefinition向ioc容器注册完成之后,发送消息
----> <bean>标签解析处理
String id = ele.getAttribute("id"); //解析id属性
String nameAttr = ele.getAttribute("name"); //解析name属性
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); //对bean元素的详细解析
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); //封装为BeanDefinitionHolder返回
-----> 对bean元素的详细解析
className = ele.getAttribute("class").trim();
parent = ele.getAttribute("parent");
AbstractBeanDefinition bd = createBeanDefinition(className, parent); //创建装在bean信息的AbstractBeanDefinition对象,实际的实现是GenericBeanDefinition -> BeanDefinitionReaderUtils.createBeanDefinition(parentName, className, this.readerContext.getBeanClassLoader()); -> GenericBeanDefinition bd = new GenericBeanDefinition(); bd.setBeanClass(ClassUtils.forName(className, classLoader));
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //解析bean标签的各种其他属性
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); //设置description信息
parseMetaElements(ele, bd); //解析元数据
parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); //解析lookup-method属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); //解析replaced-method属性
parseConstructorArgElements(ele, bd); //解析构造函数参数
parsePropertyElements(ele, bd); //解析property子元素
parseQualifierElements(ele, bd); //解析qualifier子元素
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
--> 自定义标签解析
String namespaceUri = getNamespaceURI(ele); //获取对应的命名空间
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); //根据命名空间找到对应的NamespaceHandlerspring, 如:
handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); //调用自定义的NamespaceHandler进行解析
上面几步总结, 解析过程是由documentLoader完成的, 从String[] -> String -> Resource[] > Resource, 最终将resource读取成一个document文档,根据document文档的节点信息, 封装成一个个的BeanDefinition对象;
标签:bd,标签,ele,alias,bean,详解,obtainFreshBeanFactory,解析,方法 From: https://www.cnblogs.com/superpiter/p/18031587