自己动手写spring(一) 使用digester
来源:互联网 发布:随机森林算法matlab 编辑:程序博客网 时间:2024/04/30 08:41
前言
本来想熟悉下digester的使用,写着写着发现,可以搞一个类似spring的东西的来,将过程记录下来,与大家分享。
例子中很多代码没有优化,基本没有异常处理和判空操作,这是我的一个坏习惯,先奔着目的去,实现成功后再重构。但这样的代码,更易看懂,优化后的代码反而掩盖了很多思路和思想,尤其容易让人分不清重点(因为算是技巧的地方太多了)。
项目源码的git clone地址:git@code.csdn.net:lqk654321/lspring.git
使用digester读取一个配置文件
digester入门的例子通常是
<?xml version="1.0" encoding="UTF-8"?><books> <book> <author>Author 2</author> <title>His One Book</title> </book></books>
digester代码
public class BookMain { public static void main(String[] args) throws IOException, SAXException { Digester digester = new Digester(); digester.setValidating(false); // 创建对象 digester.addObjectCreate("books", Books.class); digester.addObjectCreate("books/book", Book.class); // 设置属性 digester.addBeanPropertySetter("books/book/author", "author"); digester.addBeanPropertySetter("books/book/title", "title"); // 处理对象之间的关系 digester.addSetNext("books/book", "addBook"); InputStream in = ClassLoader.getSystemResourceAsStream("books.xml"); Books bs = (Books) digester.parse(in); System.out.println(bs.getBooks().get(0)); }}
这个xml文件的配置跟我们常用的不太一样,很明显,常见的是下面这种:
<books> <book author="author" title="title" class="org.lqk.digester.book.Book"/></books>
对应的处理类
public class BookMain2 { public static void main(String[] args) throws IOException, SAXException { Digester digester = new Digester(); digester.setValidating(false); digester.addObjectCreate("books", Books.class); digester.addObjectCreate("books/book", "org.lqk.digester.book.Book","class"); digester.addSetProperties("books/book"); digester.addSetNext("books/book", "addBook"); InputStream in = ClassLoader.getSystemResourceAsStream("books2.xml"); Books bs = (Books) digester.parse(in); System.out.println(bs.getBooks().get(0)); }}
这个跟常用的就像很多了。从这个例子中可以看到,根据配置文件,我们是可以搞出一些类来,并处理它们之间的关系。说的抽象点,我们可以将配置文件描述的信息,映射到jvm的类中。
spring样式的配置文件
那对于一个spring样式的配置文件,兴许也能搞出点东西来。
<beans> <!-- 目前的局限 1. 必须包括id和class两个属性 --> <!-- <bean>标签中的name属性对Bean类有意义,但对beanA和beanB确没有意义 --> <bean id="beanA" name="test" class="org.lqk.container.bean.BeanA"> <property name="beanB" ref="beanB"/> <property name="title" value="studentA"/> </bean> <bean id="beanB" class="org.lqk.container.bean.BeanB"> <property name="title" value="studentB"/> </bean></beans>
我们先来尝试读取基本信息。首先是创建三个model,将标签信息对象化(你该不会想直接用digester生成beanA吧!),model中省略set和get方法(但是必须要有的喔)。
public class Beans { private List<Bean> beans = new ArrayList<Bean>(); public void addBean(Bean bean){ this.beans.add(bean); }}public class Bean { private String className; private String id; private List<Property> props = new ArrayList<Property>(); public void addProperty(Property property){ this.props.add(property); }} public class Property { private String name; private String value; private String ref;}public class Main { public static void main(String[] args) throws IOException, SAXException { Digester digester = new Digester(); digester.setValidating(false); digester.addObjectCreate("beans", Beans.class); // 如果配置文件中有多个bean,add一次即可 digester.addObjectCreate("beans/bean", Bean.class); // 设置bean的属性<bean name="",id="">中的id和name。默认属性名和类中的属性名一样,不同的要特殊配置 digester.addSetProperties("beans/bean", "class", "className"); digester.addSetProperties("beans/bean"); digester.addObjectCreate("beans/bean/property", Property.class); // 将标签中的属性赋给对象 digester.addSetProperties("beans/bean/property"); // 设置对象间的关系 digester.addSetNext("beans/bean/property", "addProperty"); digester.addSetNext("beans/bean", "addBean"); InputStream in = ClassLoader.getSystemResourceAsStream("beans.xml"); Beans beans = (Beans) digester.parse(in); List<Bean> beanList = beans.getBeans(); for (Bean bean : beanList) { System.out.println("bean =================================================>"); System.out.println(" id ==> " + bean.getId()); List<Property> props = bean.getProps(); for (Property prop : props) { System.out.println(" property =================================================>"); System.out.println(" name ==> " + prop.getName()); System.out.println(" ref ==> " + prop.getRef()); System.out.println(" value ==> " + prop.getValue()); } } }}
现在信息从配置文件转到了jvm中,以类的形式存在。我们可以通过Class.forName(className)
加载真正的beanA进入jvm。柿子捡软的捏,我们先创建一个beanB出来。
public class Main2 { public static void main(String[] args) throws Exception { // 省略上述代码 for (Bean bean : beanList) { if("org.lqk.container.bean.BeanB".equals(bean.getClassName())){ // 加载类并创建对象 Class clazz = Class.forName("org.lqk.container.bean.BeanB"); Object obj = clazz.newInstance(); // 为对象属性赋值 List<Property> props = bean.getProps(); String methodName = "set" + bigCaseFirstChar(props.get(0).getName()); Method m = clazz.getMethod(methodName, String.class); m.invoke(obj, props.get(0).getValue()); // 使用对象 BeanB beanB = (BeanB)obj; System.out.println(beanB.getTitle()); break; } } } // 将该字符串的首字母大写 public static String bigCaseFirstChar(String prop) { char ch = (char) (prop.charAt(0) - 32); return prop.replaceFirst(prop.charAt(0) + "", ch + ""); }}
我们真的弄了一个类出来,虽然对经常用spring的人来说有点大惊小怪,但亲身体验一把,还是很有意义的。
1 0
- 自己动手写spring(一) 使用digester
- 自己动手写代码,整合Spring和Hibernate(一)和FactoryBean的使用
- 自己动手写俄罗斯方块(一)
- 自己动手写操作系统(一)
- 自己动手写操作系统(一)
- spring - 自己动手写spring
- 自己动手写spring(六) 支持FactoryBean
- 自己动手写spring(八) 支持AOP
- 自己动手写spring(九) 总结
- 自己动手写Kinect程序(一)
- 自己动手写PHP框架(一)
- 《自己动手写操作系统》实践(一)
- 自己动手写操作系统(一)
- 自己动手写操作系统(一)
- 自己动手写操作系统(一)
- 自己动手写俄罗斯方块(一)
- 自己动手写操作系统(一)
- 自己动手写string类(一)
- Python xlrd、xlwt、xlutils修改Excel文件
- 全文索引 Lucene初探
- cots 常见问题解答
- Python中map()函数浅析
- 诗意回文
- 自己动手写spring(一) 使用digester
- 活动h5页面倒计时效果
- windows server 2012 standard eval评估板过期-解决方法
- Windows Caffe中MNIST数据格式转换实现
- Windows文件和文件夹定期清理
- svn的备份还原(一)
- 安装
- Mac 读写文件
- 解决Android Studio中Terminal无法输入问题