采用dom4j和反射模拟Spring框架的依赖注入功能
Posted 大胡龙的小圈子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了采用dom4j和反射模拟Spring框架的依赖注入功能相关的知识,希望对你有一定的参考价值。
Spring的依赖注入是指将对象的创建权交给Spring框架,将对象所依赖的属性注入进来的行为.在学习了dom4j后,其实也可以利用dom4j和反射做一个小Demo模拟Spring框架的这种功能.下面是具体的步骤:
第一步,编写配置文件.配置文件的书写,采用了和Spring的配置文件applicationContext.xml一样的书写规则:
<?xml version="1.0" encoding="UTF-8"?> <!-- applicationContext.xml配置文件 --> <beans> <bean id="student1" class="com.xyy.domain.Student"> <property name="name" value="hlhdidi"></property> <property name="age" value="13"></property> <property name="teacher" ref="teacher1"></property> </bean> <bean id="teacher1" class="com.xyy.domain.Teacher"> <property name="name" value="cwb"></property> <property name="classes" value="高三九班"></property> </bean> </beans>
第二步,编写JavaBean类,书写了两个JavaBean,其中Student类中有一个Teacher类的引用.
//Student类 public class Student implements Serializable{ private String name; private int age; private Teacher teacher; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Teacher getTeacher() { return teacher; } public void setTeacher(Teacher teacher) { this.teacher = teacher; } @Override public String toString() { return "Student [name=" + name + ", age=" + age + ", teacher=" + teacher + "]"; } }
//Teacher类 public class Teacher implements Serializable{ private String name; private String classes; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClasses() { return classes; } public void setClasses(String classes) { this.classes = classes; } @Override public String toString() { return "Teacher [name=" + name + ", classes=" + classes + "]"; } }
第三步,也是最关键的一步,编写MyClassPathXmlApplicationContext类,在这个类里面做了如下操作:
1.利用传入的参数获取xml文件的流,并且利用dom4j解析成Document对象
2.对于Document对象获取根元素对象<beans>后对下面的<bean>标签进行遍历,判断是否有符合的id.
3.如果找到对应的id,相当于找到了一个Element元素,开始创建对象,先获取class属性,根据属性值利用反射建立对象.
4.遍历<bean>标签下的property标签,并对属性赋值.注意,需要单独处理int,float类型的属性.因为在xml配置中这些属性都是以字符串的形式来配置的,因此需要额外处理.
5.如果属性property标签有ref属性,说明某个属性的值是一个对象,那么根据id(ref属性的值)去获取ref对应的对象,再给属性赋值.
6.返回建立的对象,如果没有对应的id,或者<beans>下没有子标签都会返回null
代码如下:
public class MyClassPathXmlApplicationContext { private String xmlName; public MyClassPathXmlApplicationContext(String xmlName) { this.xmlName=xmlName; } public Object getBean(String id) { Object obj=null; //声明引用. //进行xml的解析 SAXReader reader=new SAXReader(); try { Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(xmlName)); Element root=document.getRootElement(); //遍历.看是否有元素的id为传入的参数. List<Element> elements = root.elements(); if(elements.size()>0) { for(Element element:elements ) { if(element.attributeValue("id").equals(id)) {//id相同开始创建对象 //采用反射创建对象. String className=element.attributeValue("class"); Class beanClass=Class.forName(className); obj=beanClass.newInstance(); //获取子标签的属性. List<Element> attributes=element.elements(); if(attributes.size()>0) { for(Element attribute:attributes) { String name=attribute.attributeValue("name"); Field field = beanClass.getDeclaredField(name); field.setAccessible(true); if(attribute.attribute("ref")!=null) { //此属性的值是一个对象.这里由于直接调用getBean方法赋值给对象,返回的对象一定是Bean参数的对象,因此强制转换不会出问题 String refid=attribute.attributeValue("ref"); field.set(obj, getBean(refid)); } else { //此属性值是一个字符串.这里单独处理int,float类型变量.如果不处理,会将String类型直接赋值给int类型,发生ClassCastException String value=attribute.attributeValue("value"); //需要对类型进行判断 if(value.matches("[0-9]+")) { //整数 int x=Integer.parseInt(value); field.set(obj, x); continue; } if(value.matches("[0-9]*(\\.+)[0-9]*")) { //浮点数 float y=Float.parseFloat(value); field.set(obj, y); //注意double可以接受float类型 continue; } field.set(obj, value);//处理String类型 } } } } } } } catch (Exception e) { e.printStackTrace(); } return obj; } }
第四步:测试.
@Test public void testMySpring() { MyClassPathXmlApplicationContext applicationContext=new MyClassPathXmlApplicationContext("applicationContext.xml"); System.out.println(applicationContext.getBean("student1")); }
测试结果:
Student [name=hlhdidi, age=13, teacher=Teacher [name=cwb, classes=高三九班]]
总结:
dom4j是一个很好的解析xml的工具,而解析xml是一个很重要的基本功,对于理解框架原理有很大的帮助.反射结合xml文件的解析,可以实现在任何类中方便的创建任何对象.
以上是关于采用dom4j和反射模拟Spring框架的依赖注入功能的主要内容,如果未能解决你的问题,请参考以下文章