第五章 Spring XML配置原理

Spring XML配置原理

XML基本概念
1、XML基本概念

XML(eXtensible Markup Language)是一种用于存储和传输数据的标记语言,其核心功能是承载和交换结构化信息,而非像HTML那样专注于数据的显示。

特点:可扩展性(用户自定义标签)、平台无关性、结构性、数据与显示分离‌

  • 可扩展性(用户自定义标签): XML允许用户定义自己的标记(即标签),这意味着XML文档的结构可以非常灵活地适应不同的应用需求。例如,你可以在XML文档中定义任何你需要的标签,如<student><course>等,而不必依赖于预定义的标签集

  • **平台无关性:**XML文档在不同的操作系统和软件平台上具有相同的表示方式,这意味着一个XML文件可以在任何支持XML解析的平台上被读取和解析,而不会出现格式上的差异。

  • 结构性:XML文档的结构由标签(elements)和属性(attributes)组成,这些元素和属性可以嵌套来构建复杂的文档结构。XML使用开始标签、结束标签和可选的属性来定义数据的结构。

  • **数据与显示分离:**XML本身只关注数据的结构和内容,而不涉及数据的显示方式。数据的显示通常通过XSLT(Extensible Stylesheet Language Transformations)或CSS(Cascading Style Sheets)等技术来实现,这些技术可以将XML数据转换为不同的格式或布局。

2、XML解析概述

XML解析技术主要分为两大类:基于树的解析基于事件的解析,每种方式各有特点和应用场景

2.1、基于树的解析(DOM解析)

  • 将整个XML文档一次性加载到内存中,形成树状结构,允许随机访问节点。

  • 优点:支持增删改查操作,适合需要频繁修改XML的场景。

  • 缺点:内存占用高,不适合处理大型XML文件。

  • 典型实现:JAXP(Java API for XML Processing) Java官方实现,支持DOM标准,适用于服务器端开发,但性能中等‌、**DOM4j(性能更优的非官方解析器)**专为Java设计的高效开源解析器,提供简洁API(如链式调用),支持XPath查询和命名空间,常用于配置文件管理和数据交换‌。其核心接口包括Element、Attribute等,易于上手且灵活性高‌

2.2、基于事件解析

  • 逐行读取XML文件,通过事件回调机制处理数据。

  • 优点:内存占用低,适合处理大型文件。

  • 缺点:仅支持读取,无法修改XML内容。

  • 典型实现:**SAX解析器(Java内置)**Java标准库的一部分,内存效率高,常用于日志处理或大型数据导入‌

3、其他解析技术与工具

  • XPath/XQuery‌:非独立解析器,而是查询语言,常与DOM或SAX结合使用,通过路径表达式快速定位节点(如DOM4j的XPath支持)‌。
基于树形解析使用dom4j

依赖

XML 复制代码
   <!--    导入dom4j相关依赖-->
     <dependency>
       <groupId>org.dom4j</groupId>
       <artifactId>dom4j</artifactId>
       <version>2.2.0</version>
     </dependency>

使用反射的思想自定义方法获取配置文件中的数据并进行赋值

  1. 创建实体类

    java 复制代码
     @Data
     public class Account {
         private Orders orders;
     }
    Orders
    
     @Data
     public class Orders {
         private String oid;
         private String createtime;
     }
  2. 创建自定义的核心配置文件

    XML 复制代码
    <beans>
         <bean id="order" class="com.wn.entity.Orders">
             <property name="createtime" value="2015/12/10 10:20:30"/>
             <property name="oid" value="2015"/>
         </bean>
         <bean id="account" class="com.wn.entity.Account">
             <property name="orders" ref="order"/>
         </bean>
     </beans>
  3. 创建IOCBeanFactory类

    java 复制代码
     package com.wn.util;
     ​
     import org.dom4j.Document;
     import org.dom4j.DocumentException;
     import org.dom4j.Element;
     import org.dom4j.io.SAXReader;
     ​
     import java.io.InputStream;
     import java.lang.reflect.Method;
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
     ​
     /**
      * 解析XML文件,获取xml中元素,创建对象并注入对象相关bean依赖
      */
     public class IOCBeanFactory {
     ​
         /**
          * 创建Map集合,存放创建 实体对象
          */
         private Map<String,Object> map = new HashMap<String,Object>();
     ​
         /**
          * 通过构造方法 ,获取需要解析的xml文件
          */
         public IOCBeanFactory(String xmlConfiguration) throws Exception {
             //调用方法,解析xml文件
             parseXmlFile(xmlConfiguration);
         }
     ​
         /**
          * 解析xml文件,通过反射创建 指定类型对象 和 给对象注入属性
          * @param xmlConfiguration  配置文件名称
          */
         private void parseXmlFile(String xmlConfiguration) throws Exception {
             //1.获取该配置文件InputStream流对象
             InputStream is = IOCBeanFactory.class.getClassLoader().getResourceAsStream(xmlConfiguration);
            //2.创建SaxReader对象
             SAXReader reader = new SAXReader();
             //3.读取xml配置文件InputStream形式流对象,返回Document对象
             Document document = reader.read(is);
             //4.获取文件中根标签,返回元素对象
             Element rootElement = document.getRootElement();
             //5.获取跟标签下Bean标签
             List<Element> beanList = rootElement.elements("bean");
             //6.遍历集合
             for(Element bean : beanList){
                 //7.获取bean标签中id和class属性
                 String id = bean.attributeValue("id");
                 String className = bean.attributeValue("class");
                 //8.获取指定类的字节码对象
                 Class<?> clazz = Class.forName(className);
                 //9.创建对象
                 Object instance = clazz.newInstance();
                 //10.获取当前bean标签下所有property标签元素
                 List<Element> plist = bean.elements("property");
                 //11.遍历plist集合
                 for(Element property : plist){
                     //12.获取当前property元素的name、value、ref属性的值
                     String name = property.attributeValue("name");
                     String value = property.attributeValue("value");
                     String ref = property.attributeValue("ref");
                     //13.生成属性的set方法名称
                     String methodName = "set"+ name.substring(0, 1).toUpperCase() + name.substring(1 );  //oid   setOid
                     //14.获取当前对象中所有方法
                     Method[] methods = clazz.getMethods();
                     //15.遍历数组
                     for(Method m : methods){
                         //16.判断方法名称是否一致
                         if(methodName.equals(m.getName())){ //表示当前set方法存在,则进行调用set方法
                             //17.判断value是否有值
                             if(value != null){
                                 //18.调用set方法
                                 m.invoke(instance, value);
                             }else if(ref != null){ //表示ref属性不为空,表示复杂类型赋值
                                 m.invoke(instance, getObject(ref));
                             }
                         }
                     }
                 }
                 //把对象添加到map集合中
                 map.put(id,instance);
             }
         }
         /**
          * 通过key获取map集合中对应value值
          */
         public Object getObject(String id){
             return map.get(id);
         }
     }
  4. 测试

    java 复制代码
    public class BeanFactoryTest {
         public static void main(String[] args) throws Exception {
     ​
             //1.加载指定xml配置文件,创建IOCBeanFactory对象
             IOCBeanFactory factory = new IOCBeanFactory("springIoc.xml");
             //2.获取map集合中指定id对应对象
             Account account = (Account) factory.getObject("account");
     ​
             System.out.println(account);
         }
     }
相关推荐
江上鹤.1481 小时前
Day25评价问题
python
万行1 小时前
英语作文模板
python
韩立学长1 小时前
【开题答辩实录分享】以《计算机类专业招聘信息爬取与查询系统设计与实现》为例进行答辩实录分享
python·scrapy·django
kyle~1 小时前
虚拟仪器LabView(VI)
c++·python·ros·labview
风萧萧19991 小时前
Java:PPT转图片
java·python·powerpoint
洲星河ZXH1 小时前
Java,日期时间API
java·开发语言·python
秋邱1 小时前
AR 定位技术深度解析:从 GPS 到视觉 SLAM 的轻量化实现
开发语言·前端·网络·人工智能·python·html·ar
Boop_wu1 小时前
[Java EE] 多线程进阶(3) [线程安全集合类]
开发语言·windows·python
木棉知行者2 小时前
(二)Python基本语句
开发语言·python