XML
三大对象:
- BeanDefinition:是 Spring 中极其重要的一个概念,存储了 bean 对象的所有特征信息,如是否单例、是否懒加载、factoryBeanName 等,和 bean 的关系就是类与对象的关系,一个不同的 bean 对应一个 BeanDefinition
- BeanDefinationRegistry:存放 BeanDefination 的容器,是一种键值对的形式,通过特定的 Bean 定义的 id,映射到相应的 BeanDefination,BeanFactory 的实现类同样继承 BeanDefinationRegistry 接口,拥有保存 BD 的能力
- BeanDefinitionReader:读取配置文件,XML 用 Dom4j 解析,注解用 IO 流加载解析
程序:
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));
UserService userService1 = (UserService)bf.getBean("userService");
源码解析:
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}
public int loadBeanDefinitions(Resource resource) {
//将 resource 包装成带编码格式的 EncodedResource
//EncodedResource 中 getReader()方法,调用java.io包下的 转换流 创建指定编码的输入流对象
return loadBeanDefinitions(new EncodedResource(resource));
}
-
XmlBeanDefinitionReader.loadBeanDefinitions():把 Resource 解析成 BeanDefinition 对象currentResources = this.resourcesCurrentlyBeingLoaded.get():拿到当前线程已经加载过的所有 EncodedResoure 资源,用 ThreadLocal 保证线程安全if (currentResources == null):判断 currentResources 是否为空,为空则进行初始化if (!currentResources.add(encodedResource)):如果已经加载过该资源会报错,防止重复加载inputSource = new InputSource(inputStream):资源对象包装成 InputSource,InputSource 是 SAX 中的资源对象,用来进行 XML 文件的解析return doLoadBeanDefinitions():加载返回currentResources.remove(encodedResource):加载完成移除当前 encodedResourceresourcesCurrentlyBeingLoaded.remove():ThreadLocal 为空时移除元素,防止内存泄露
-
XmlBeanDefinitionReader.doLoadBeanDefinitions(inputSource, resource):真正的加载函数Document doc = doLoadDocument(inputSource, resource):转换成有层次结构的 Document 对象getEntityResolver():获取用来解析 DTD、XSD 约束的解析器getValidationModeForResource(resource):获取验证模式
int count = registerBeanDefinitions(doc, resource):将 Document 解析成 BD 对象,注册(添加)到 BeanDefinationRegistry 中,返回新注册的数量-
createBeanDefinitionDocumentReader():创建 DefaultBeanDefinitionDocumentReader 对象 -
getRegistry().getBeanDefinitionCount():获取解析前 BeanDefinationRegistry 中的 bd 数量 -
registerBeanDefinitions(doc, readerContext):注册 BD-
this.readerContext = readerContext:保存上下文对象 -
doRegisterBeanDefinitions(doc.getDocumentElement()):真正的注册 BD 函数doc.getDocumentElement():拿出顶层标签
-
-
return getRegistry().getBeanDefinitionCount() - countBefore:返回新加入的数量
-
DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions():注册 BD 到 BR-
createDelegate(getReaderContext(), root, parent):beans 是标签的解析器对象 -
delegate.isDefaultNamespace(root):判断 beans 标签是否是默认的属性 -
root.getAttribute(PROFILE_ATTRIBUTE):解析 profile 属性 -
preProcessXml(root):解析前置处理,自定义实现 -
parseBeanDefinitions(root, this.delegate):解析 beans 标签中的子标签-
parseDefaultElement(ele, delegate):如果是默认的标签,用该方法解析子标签- 判断标签名称,进行相应的解析
processBeanDefinition(ele, delegate):
-
delegate.parseCustomElement(ele):解析自定义的标签
-
-
postProcessXml(root):解析后置处理
-
-
DefaultBeanDefinitionDocumentReader.processBeanDefinition():解析 bean 标签并注册到注册中心-
delegate.parseBeanDefinitionElement(ele):解析 bean 标签封装为 BeanDefinitionHolder-
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()):条件一成立说明 name 没有值,条件二成立说明别名有值beanName = aliases.remove(0):拿别名列表的第一个元素当作 beanName -
parseBeanDefinitionElement(ele, beanName, containingBean):解析 bean 标签parseState.push(new BeanEntry(beanName)):当前解析器的状态设置为 BeanEntry- class 和 parent 属性存在一个,parent 是作为父标签为了被继承
createBeanDefinition(className, parent):设置了class 的 GenericBeanDefinition对象parseBeanDefinitionAttributes():解析 bean 标签的属性- 接下来解析子标签
-
beanName = this.readerContext.generateBeanName(beanDefinition):生成 className + # + 序号的名称赋值给 beanName -
return new BeanDefinitionHolder(beanDefinition, beanName, aliases):包装成 BeanDefinitionHolder
-
-
registerBeanDefinition(bdHolder, getReaderContext().getRegistry()):注册到容器beanName = definitionHolder.getBeanName():获取beanNamethis.beanDefinitionMap.put(beanName, beanDefinition):添加到注册中心
-
getReaderContext().fireComponentRegistered():发送注册完成事件
-
本文正在参加「金石计划 . 瓜分6万现金大奖」
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/4505.html