数据交换格式--02(xml)+SpringIOC底层实现

本文深入探讨了XML文档的结构与解析方法,包括DOM4J与SAX两种主流解析方式的区别与应用场景,并通过实例展示了如何使用Java反射机制对XML文件进行解析与对象实例化,同时介绍了SpringIOC框架中对这两种技术的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

xml定义:是一种可扩展标记语言,简称xml,是一种标记语言,
xml全称为可扩展的标记语言,主要用于描述数据和用作配置文件。
xml文档在逻辑上主要由以下5个部分组成:
xml声明:指出xml文档所用的DTD。
文档类型声明:指明所用的xml的版本,文档的编码,文档的独立性信息。
元素:由开始标签,元素内容和结束标签构成。
注释:已结束,用于文档中的内容起一个说明的作用。
处理指令:通过处理指令来通知其他的应用程序来处理非xml格式的数据。
xml文档的根元素被称为文档元素,他和在其外部出现的处理指令,注释等作为文档实体的子节点,根元素本身和其内部的子元素也是一棵树。
xml存储结构类似于树状结构。
解析XMl常用的方式:
Dom4J SAX两种方式:
区别:Dom4j不适合大文件的解析,因为它是一下子将文件加载到内存中,所以可能出现内存溢出。sax是基于事件来对xml进行解析的,所以她可以解析大文件的xml,也正是因为这样,所以Dom4j可以对xml进行灵活的增删茶和导航,而sax没有这么强的灵活性,所以sax经常是用来解析大型的xml文件,而要对xml进行灵活的增删操作 就用Dom4j。
简单的例子解析xml:

package com.itmayiedu.day01;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.util.Iterator;
import java.util.List;

/**
 * 解析xml
 */
public class XmlTest {

    public static void main(String[] args) throws Exception{
        test01();
    }
    public static void test01() throws Exception{
            ///Users/yantianpeng/Desktop/xmltest.txt;
        //h获取都读取对象。
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read("/Users/yantianpeng/Desktop/xmltext.txt");
        Element rootElement = document.getRootElement();
        getNodes(rootElement);

    }
    //      获取节点并判断是否存在下一个节点
    public static void getNodes(Element rootElement){
        List<Attribute> attributes = rootElement.attributes();
        for (Attribute attribute:attributes) {
            System.out.println("属性的名字是:"+attribute.getName()+"属性的值是:"+attribute.getValue());
        }
        String textTrim = rootElement.getTextTrim();
        if(!"".equals(textTrim)){
            System.out.println("节点名称:"+rootElement.getName()+" 节点Value:"+textTrim);
        }
        Iterator<Element> elementIterator = rootElement.elementIterator();
        while (elementIterator.hasNext()){
            Element next = elementIterator.next();
            getNodes(next);//递归算法获取下一个节点。
        }
    }
}

Java反射机制:
动态运行获取当前类的所有信息。当使用类是不用new 使用Java的反射机制帮你去初始化。
反射机制的核心:当前类的class文件。
Java反射机制的作用:
提高程序的扩展性,封装工具类,框架应用。
Java应用场景:SpringIOC Jdbc数据链接 框架里面用到。
使用有参数的构造起和无参数的构造起实力化类:

   //使用java的有参数的构造函数获取类的实力化
    public static void test02()throws Exception {
        Class<?> forName = Class.forName("com.itmayiedu.day01.User");
        //使用有参数的构造函数
        Constructor<?> constructor = forName.getConstructor(Integer.class, String.class);
        User user1 = (User) constructor.newInstance(1, "12233");
        System.out.println(user1.getName());
        System.out.println(user1.getId());
    }
   //使用java的有参数的构造函数获取类的实力化
    public static void test02()throws Exception {
        Class<?> forName = Class.forName("com.itmayiedu.day01.User");
        //使用有参数的构造函数
        Constructor<?> constructor = forName.getConstructor(Integer.class, String.class);
        User user1 = (User) constructor.newInstance(1, "12233");
        System.out.println(user1.getName());
        System.out.println(user1.getId());
    }

使用Java的反射机制获取类的所有属性和方法并且为私有属性赋值。
为私有的属性赋值:

    public static void test04() throws Exception{
        Class<?> forName = Class.forName("com.itmayiedu.day01.User");
        User newInstance = (User)forName.newInstance();
        Field[] declaredFields = forName.getDeclaredFields();
        for (Field field:declaredFields) {
            Field declaredField = forName.getDeclaredField(field.getName());
            declaredField.setAccessible(true);//私有属性必须设置此属性是true
            Class<?> type = declaredField.getType();
            if("Integer".equals(type.getSimpleName())){
                declaredField.set(newInstance,1);
            }
            if("String".equals(type.getSimpleName())){
                declaredField.set(newInstance,"ioioi");
            }
        }
        System.out.println(newInstance.getName());
        System.out.println(newInstance.getId());
    }

获取当前类的所有的方法:

    public static void test03()throws Exception {
        Class<?> forName = Class.forName("com.itmayiedu.day01.User");
        Field[] declaredFields = forName.getDeclaredFields();//获取当前累的的所有的属性
        for (Field field:declaredFields) {
            System.out.println(Modifier.toString(field.getModifiers())+" "+field.getType()+" "+field.getName());
        }
        System.out.println();
        Method[] declaredMethods = forName.getDeclaredMethods();//获取当前类的所有的方法
        for (Method method:declaredMethods) {
           System.out.println(Modifier.toString(method.getModifiers())+" "+method.getReturnType()+" "+" "+method.getName()
           +"("+")");
        }
    }

Spring IOC底层是通过Dom4j加上Java反射
可以通过下面的代码实现:

package com.itmayiedu.day01;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.lang.reflect.Field;
import java.util.List;

public class ClassPathXmlApplicationContext {
        private static String path;
        private static String ID;
        private static String CLASS;
        private static String NAME;
        private static String VALUE;
        private void init(){
            ID="id";
            CLASS ="class";
            NAME ="name";
            VALUE  ="value";
        }
        //通过构造函数读取文件xml
    public ClassPathXmlApplicationContext(String path) {
            init();
        this.path =path;
    }
    //通解析xml获取xml里面的值
    public static Object getBean(String beanId)throws Exception{
            //判断beanId是否是空
       if(isEmpty(beanId)){
          throw new Exception("beanId不能为空");
       }
       //读取xml文件
        SAXReader saxReader = new SAXReader();
        Document read = saxReader.read(path);
        Element rootElement = read.getRootElement();
        List<Element> elements = rootElement.elements();//获取根节点
        for (Element element:elements) {
            String id = element.attributeValue(ID);
            if(!id.equals(beanId)){
                //结束本次循环
                continue;
            }
            //从配置文件中获到bena
            String attClass = element.attributeValue(CLASS);
            //使用Java反射机制获取初始化类
           Class<?> forName = Class.forName(attClass);
            User user = (User)forName.newInstance();
            List<Element> Sonelement = element.elements();//获取二级节点
            for (Element Sonel: Sonelement) {
                String attrFiled = Sonel.attributeValue(NAME);
                String attributeValue = Sonel.attributeValue(VALUE);//给属性赋值
                Field declaredField = forName.getDeclaredField(attrFiled);
                declaredField.setAccessible(true);
                String type = declaredField.getType().getSimpleName();
                if("Integer".equals(type)){
                    declaredField.set(user,Integer.parseInt(attributeValue));
                }
                if("String".equals(type)){
                    declaredField.set(user,(attributeValue));
                }

            }
            return user;

        }
        return null;
    }

    /**
     * 判断是否为空
     * @param string
     * @return
     */
    public static boolean isEmpty(String string){
        if("".equals(string)||null ==string||string.trim().length()==0){
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext applicationContext =new
                ClassPathXmlApplicationContext("/Users/yantianpeng/Desktop/xmltext.txt");
        User user1 = (User)getBean("      ");
        System.out.println(user1.getId());
        System.out.println(user1.getName());
    }
}

xml格式如下:

<?xml version="1.0"?>
<beans>
    <bean id="user1" class="com.itmayiedu.day01.User">
        <property name="id" value="0001"></property>
        <property name="name" value="zhangdan"></property>
        </bean>
        <bean id="user2" class="com.itmayiedu.day01.User">
            <property name="id" value="0002"></property>
            <property name="name" value="Shanghai"></property>
        </bean>
</beans>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值