博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
扒一扒spring,dom4j实现模拟实现读取xml
阅读量:5060 次
发布时间:2019-06-12

本文共 5834 字,大约阅读时间需要 19 分钟。

今天leadr提出需求,原来公司项目中读取解析xml文件的代码效率太低,考虑切换一种xml为数据封装格式与读取方式以提高效率。我这灵机一动spring对bean的依赖注入就是读取xml文件,可以尝试扒一扒spring的源码,来实现一个轻量级的方案。

重构xml文件,向spring的xml文件格式看齐

重构完成的xml文件格式如下:

看起来很眼熟的有没有,跟spring的配置文件一样哦。

扒一扒spring读取xml文件的源码

手动扒了一下spring读取xml文件的代码,由于spring过于庞大,读取spring的xml方法又按照读取不同的标签被分拆出n多个方法,楼主能力有限就不在这里卖弄了,不过spring从配置文件把bean加载到bean工厂跟楼主下面读取xml文件的方式理论上是一样的。

废话不多说,上代码:

/** * 模拟spring依赖注入的方式读取xml文件. * @author whf * @date Aug 23, 2017 */public class XMLBeanFactory {
private String xmlName; private SAXReader reader; private Document document; /** * 构造方法. * @param xmlName xmlName. */ public XMLBeanFactory(String xmlName) { // 在构造方法中 try { this.xmlName = xmlName; reader = new SAXReader(); document = reader.read(this.getClass().getClassLoader().getResourceAsStream(xmlName)); } catch (DocumentException e) { e.printStackTrace(); } } /** * 获取相同类型的bean. * @param type bean的class type. * @return 返回相同类型的bean的list. * @throws Exception Exception. */ public
List
getBeansOfType(Class
type) throws Exception { List
objects = new ArrayList<>(); try { Element root = document.getRootElement(); List
beans = root.elements(); if (beans.size() > 0) { for (Element bean : beans) { if (bean.attributeValue("class").equals(type.getName())) { T object = null; String clazz = bean.attributeValue("class"); // 通过反射来创建对象 Class beanClass = Class.forName(clazz); object = (T) beanClass.newInstance(); List
propertys = bean.elements(); if (propertys.size() > 0) { for (Element property : propertys) { String key = property.attributeValue("name"); Field field = beanClass.getDeclaredField(key); field.setAccessible(true); List
childBean = property.elements(); // 如果property下内嵌bean if (childBean.size() > 0) { Object childObject = getBean(key, property); field.set(object, childObject); } else { /* * 此属性值是一个字符串.这里单独处理int,float类型变量.如果不处理, * 会将String类型直接赋值给int类型,发生ClassCastException */ String value = property.attributeValue("value"); // 需要对类型进行判断 if (field.getType().getName().equals("int")) { // 整数 int x = Integer.parseInt(value); field.set(object, x); continue; } if (field.getType().getName().equals("float")) { // 浮点数 float y = Float.parseFloat(value); field.set(object, y); // 注意double可以接受float类型 continue; } field.set(object, value);// 处理String类型 } } } objects.add(object); } } } } catch (Exception e) { e.printStackTrace(); } return objects; } /** * 获取property内嵌的bean. * @param name id或者bean的name * @param root 根节点. * @return 返回封装完整的bean. * @throws Exception Exception. */ public Object getBean(String name, Element root) throws Exception { Object object = null; List
beans = root.elements(); if (beans.size() > 0) { for (Element bean : beans) { if (bean.attributeValue("name").equals(name)) { // 如果bean name相同则开始创建对象 String clazz = bean.attributeValue("class"); // 通过反射来创建对象 Class beanClass = Class.forName(clazz); object = beanClass.newInstance(); List
propertys = bean.elements(); if (propertys.size() > 0) { for (Element property : propertys) { String key = property.attributeValue("name"); Field field = beanClass.getDeclaredField(key); field.setAccessible(true); List
childBean = property.elements(); // 如果property下内嵌bean if (childBean.size() > 0) { field.set(object, getBean(key, property)); } if (property.attribute("ref") != null) { /* * 此属性的值是一个对象.这里由于直接调用getBean方法赋值给对象,返回的对象一定是Bean参数的对象, 因此强制转换不会出问题 */ String refid = property.attributeValue("ref"); field.set(object, getBean(refid)); } else { /* * 此属性值是一个字符串.这里单独处理int,float类型变量.如果不处理,会将String类型直接赋值给int类型, * 发生ClassCastException */ String value = property.attributeValue("value"); // 需要对类型进行判断 field.set(object, value);// 处理String类型 } } } } } } return object; }}

楼主的代码就是实现读取xml文件中相同类型的bean封装到list中返回。具体如何实现,看代码,注释写的很清楚了。

文件读取的效率提升120多倍

代码完成之后,对比之前的读取xml的代码,比之前的效率提升了120。

总结一下

大牛都说要看开源框架的源码,收获会怎样怎样,但是对于大部分向我这样的伪码农去扒源码的时候总是一头雾水,不知所云。然而,当我们真正有需求的时候,开源代码的实现便成了一份巨大的宝藏,带着我们的目的去扒源码,有时候会有事半功倍的效果。楼主亲测有效,源码虽好,可不要贪杯哦。

转载于:https://www.cnblogs.com/haifeiWu/p/9079570.html

你可能感兴趣的文章
贪吃蛇游戏改进
查看>>
新作《ASP.NET MVC 5框架揭秘》正式出版
查看>>
“前.NET Core时代”如何实现跨平台代码重用 ——源文件重用
查看>>
【POJ1845】Sumdiv(数论/约数和定理/等比数列二分求和)
查看>>
在WPF中使用Caliburn.Micro搭建MEF插件化开发框架
查看>>
IdentityServer4-用EF配置Client(一)
查看>>
UWP: 掌握编译型绑定 x:Bind
查看>>
asp.net core系列 35 EF保存数据(2) -- EF系列结束
查看>>
WPF程序加入3D模型
查看>>
WPF中实现多选ComboBox控件
查看>>
读构建之法第四章第十七章有感
查看>>
C#中的IEnumerable<T>知识点
查看>>
android访问链接时候报java.net.MalformedURLException: Protocol not found
查看>>
dwz ie10一直提示数据加载中
查看>>
Windows Phone开发(4):框架和页 转:http://blog.csdn.net/tcjiaan/article/details/7263146
查看>>
Windows Phone Marketplace 发布软件全攻略
查看>>
Unity3D研究院之打开Activity与调用JAVA代码传递参数(十八)【转】
查看>>
语义web基础知识学习
查看>>
hexo个人博客添加宠物/鼠标点击效果/博客管理
查看>>
python asyncio 异步实现mongodb数据转xls文件
查看>>