Spring的XML解析原理,这一次全搞懂再走( 五 )
在这个方法中重点关注preProcessXml、parseBeanDefinitions、postProcessXml三个方法 , 其中preProcessXml和postProcessXml都是空方法 , 意思是在解析标签前后我们自己可以扩展需要执行的操作 , 也是一个模板方法模式 , 体现了Spring的高扩展性 。 然后进入parseBeanDefinitions方法看具体是怎么解析标签的:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {if (delegate.isDefaultNamespace(root)) {NodeList nl = root.getChildNodes();for (int i = 0; i < nl.getLength(); i++) {Node node = nl.item(i);if (node instanceof Element) {Element ele = (Element) node;if (delegate.isDefaultNamespace(ele)) {//默认标签解析parseDefaultElement(ele, delegate);}else {//自定义标签解析delegate.parseCustomElement(ele);}}}}else {delegate.parseCustomElement(root);} }
这里有两种标签的解析:Spring原生标签和自定义标签 。 怎么区分这两种标签呢?
// 自定义标签
如上 , 带前缀的就是自定义标签 , 否则就是Spring默认标签 , 无论哪种标签在使用前都需要在Spring的xml配置文件里声明Namespace URI , 这样在解析标签时才能通过Namespace URI找到对应的NamespaceHandler 。
xmlns:context=""
isDefaultNamespace判断是不是默认标签 , 点进去看看是不是跟我上面说的一致:
public boolean isDefaultNamespace(Node node) {return isDefaultNamespace(getNamespaceURI(node)); } public static final String BEANS_NAMESPACE_URI = ""; public boolean isDefaultNamespace(@Nullable String namespaceUri) {return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri)); }
可以看到所对应的就是默认标签 。 接着 , 我们进入parseDefaultElement方法:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {//import标签解析if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {importBeanDefinitionResource(ele);}//alias标签解析else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {processAliasRegistration(ele);}//bean标签else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {processBeanDefinition(ele, delegate);}else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {// recursedoRegisterBeanDefinitions(ele);} }
这里面主要是对import、alias、bean标签的解析以及beans的字标签的递归解析 , 主要看看bean标签的解析:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {// 解析elment封装为BeanDefinitionHolder对象BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);if (bdHolder != null) {// 该方法功能不重要 , 主要理解设计思想:装饰者设计模式以及SPI设计思想bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);try {// 完成document到BeanDefinition对象转换后 , 对BeanDefinition对象进行缓存注册BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());}// Send registration event.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));} }public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {// 获取id和name属性String id = ele.getAttribute(ID_ATTRIBUTE);String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);// 获取别名属性 , 多个别名可用,;隔开List aliases = new ArrayList
- 多就是好吗?解析智能手机多摄发展困局
- 新基建下,系统集成商数字化建设及渠道管理深度解析
- 四个维度解析区域发展与治理
- 基于Spring+Angular9+MySQL开发平台
- 智媒视角看深圳用数据解析城市
- “联邦的战斗力量”再现,华硕Z490主板机动战士高达版解析
- 天翼云全国首个工业互联网平台二级解析节点上线
- 在美国当快递小哥赚钱吗?西瓜视频解析除了努力,运气也很重要
- 蚂蚁庄园月有阴晴圆缺答案解析 12月18日今天支付宝蚂蚁庄园答案大全
- 如何做到性能翻倍 NVIDIA Ampere架构解析