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
依赖
org.dom4j
dom4j
2.2.0
使用反射的思想自定义方法获取配置文件中的数据并进行赋值
创建实体类
@Data public class Account { private Orders orders; } Orders @Data public class Orders { private String oid; private String createtime; }创建自定义的核心配置文件
创建IOCBeanFactory类
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 Mapmap = new HashMap (); /** * 通过构造方法 ,获取需要解析的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 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 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); } } 测试
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); } }
浙公网安备 33010602011771号