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>
使用反射的思想自定义方法获取配置文件中的数据并进行赋值
-
创建实体类
java@Data public class Account { private Orders orders; } Orders @Data public class Orders { private String oid; private String createtime; } -
创建自定义的核心配置文件
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> -
创建IOCBeanFactory类
javapackage 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); } } -
测试
javapublic 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); } }