spring的亿点点小细节之xml文件解析

亿点点小细节之xml文件解析

xml文件解析 是 spring的亿点点小细节之一。
核心目的就是将文件内容转为 BeanDefinition对象,并注册到BeanFactory中

学校小故事

学校小故事源链接: 学校小故事

学校spring
学校人员信息库DefaultListableBeanFactory
人员bean
人员信息BeanDefinition

最初信息规范版本:xml文件规范

学校管理局<spring开发人员>早期定义的信息完善规范,配置较为繁琐。

定义*.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

在beans中创建 bean标签

bean 的基本标签
<!--   
  bean: spring的开发人员定义标签
    属性:id<>
         class<交给spring管理的 bean的全路径>
         scope<作用域。singleton单例;prototype原型/多例。默认为单例>
    子标签:property<bean中class的构造方法参数>  value和ref二选一
       子标签属性:name<构造方法中的参数名>
                 ref<其他bean的id> 
                 value<基本数据类型>
-->
<bean id="apple" class="com.spring.cloud.moduletest.simple.Apple" autowire="byName">
    <property name="banana" ref="banana"/>
</bean>

xml文件解析

xml文件内容解析

refresh方法源头调用:
AbstractApplicationContext类中的
obtainFreshBeanFactory<创建BeanFactory>方法

XmlWebApplicationContext类中的
loadBeanDefinitions方法<完成XmlBeanDefinitionReader解析器初始化,并调用解析方法>。
doLoadDocument方法<完成读取配置文件,将配置文件内容转为Document对象>

DefaultBeanDefinitionDocumentReader类中
doRegisterBeanDefinitions方法<解析Document对象,转为BeanDefinition>
在此方法中包含以下流程
1、检查beans中的url是否存在http://www.springframework.org/schema/beans,不存在直接返回报错<找不到元素 'beans' 的声明>。
if (this.delegate.isDefaultNamespace(root)) {}
2、Document解析模板方法。
// 为子类扩展而存在,bean中方法为空方法
preProcessXml(root);
// 解析Document并注册到BeanFactory。
parseBeanDefinitions(root, this.delegate);   
// 为子类扩展而存在,bean中方法为空方法
postProcessXml(root);          
3、DefaultBeanDefinitionDocumentReader可以解析以下标签
import、alias、bean、beans
存在三种解析方法
importBeanDefinitionResource、processAliasRegistration、processBeanDefinition

bean的不常用标签

平时开发时,基本用不上。使用时搜索查一下就好,21世纪一般使用配置类检索spring管理的对象/方法,了解即可。

  bean: spring的开发人员定义标签
    属性:class<交给spring管理的 bean的全路径>
         abstract<抽象方法>
         lazy-init<懒加载,不会自动实例化,在使用时实例化>
         depends-on<需要先创建依赖bean,再将当前bean实例化>
         scope<作用域。singleton单例 prototype原型/多例>
         primary<多个同类型bean,其他bean主要引用primary为true的bean>
         init-method<初始化方法>
         destroy-method<销毁方法>
         factory-method<工厂方法>
         factory-bean<实现FactoryBean接口的bean类,使用另外一种创建对象方式>
    子标签:constructor-arg<构造方法中的参数>
       子标签属性:index<构造方法中参数下标,从0开始>
                 value<第 index 参数值>
    子标签:property<bean中class的构造方法参数>  value和ref二选一
       子标签属性:name<构造方法中的参数名>
                 ref<其他bean的id> 
                 value<基本数据类型>

自定义xml文件解析过程<炫技使用,不推荐>

21世纪的开发人员还会有人使用xml文件声明spring管理bean?不会吧😲

0、写代码之前

人类获取知识历程一般分为三个阶段:模仿,学习,创造。
对源码没有足够理解之前,请参考源码完成实现功能,再迭代进步。

1、创建xml标签处理器Handler

CustomLabelHandler参考ContextNamespaceHandler.class完成

public class CustomLabelHandler extends NamespaceHandlerSupport {

    @Override
    public void init() {
        registerBeanDefinitionParser("student", new CustomLabelParser());
    }
}

2、创建xml标签解析器Parser

CustomLabelParser参考PropertyOverrideBeanDefinitionParser.class完成

public class CustomLabelParser extends AbstractSingleBeanDefinitionParser {

    @Override
    protected Class<?> getBeanClass(Element element) {
        return Student.class;
    }

    @Override
    protected void doParse(Element element, BeanDefinitionBuilder builder) {
        if (element.hasAttribute("userName")) {
            builder.addPropertyValue("userName", element.getAttribute("userName"));
        }
        if (element.hasAttribute("password")) {
            builder.addPropertyValue("password", element.getAttribute("password"));
        }
    }
}

3、spring.handlers文件中注册handler

META-INF文件夹下创建spring.handlers文件

# *** 请自定义替换
http\://www.***.org/schema/student=*.*.*.*.CustomLabelHandler

4、spring.schemas文件声明xsd文件位置

META-INF文件夹下创建spring.schemas文件

# *** 请自定义替换
http\://www.***.org/schema/student.xsd=META-INF/student.xsd

5、xsd中规范 标签中属性

META-INF文件夹下创建student.xsd文件

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.zhaojiafeng.org/schema/student"
        xmlns:tns="http://www.zhaojiafeng.org/schema/student"
        elementFormDefault="qualified">

    <element name="student">
        <complexType>
            <attribute name="id" type="string"/>
            <attribute name="userName" type="string"/>
            <attribute name="password" type="string"/>
        </complexType>
    </element>
</schema>

6、验证自定义标签

自定义启动xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:abc="http://www.***.org/schema/student"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.***.org/schema/student
       http://www.***.org/schema/student.xsd">

    <!--- xmlns:abc  标签内属性和xsd文件中声明属性一致 -->
    <abc:student id="student" userName="userName456" password="password123"/>
    
</beans>

7、测试类验证附结果

验证测试类

    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("customLabel/customLabel.xml");
        Student bean = (Student) ac.getBean("student");
        System.out.println(bean);

        System.out.println(bean.getUserName());
        System.out.println(bean.getPassword());
    }

结果:
16:00:47.760 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@1517365b
16:00:47.913 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [customLabel/customLabel.xml]
16:00:47.937 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'student'
com.spring.cloud.moduletest.customLabel.Student@710726a3
userName456
password123

尾言

刚刚开始发布技术分享文章,如有引用,请声明引用地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值