Spring的依赖注入是指将对象的创建权交给Spring框架,将对象所依赖的属性注入进来的行为.在学习了dom4j后,其实也可以利用dom4j和反射做一个小Demo模拟Spring框架的这种功能.下面是具体的步骤:

  第一步,编写配置文件.配置文件的书写,采用了和Spring的配置文件applicationContext.xml一样的书写规则:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- applicationContext.xml配置文件 -->
  3. <beans>
  4. <bean id="student1" class="com.xyy.domain.Student">
  5. <property name="name" value="hlhdidi"></property>
  6. <property name="age" value="13"></property>
  7. <property name="teacher" ref="teacher1"></property>
  8. </bean>
  9. <bean id="teacher1" class="com.xyy.domain.Teacher">
  10. <property name="name" value="cwb"></property>
  11. <property name="classes" value="高三九班"></property>
  12. </bean>
  13. </beans>

  第二步,编写JavaBean类,书写了两个JavaBean,其中Student类中有一个Teacher类的引用.

  1. //Student类
  2. public class Student implements Serializable{
  3. private String name;
  4. private int age;
  5. private Teacher teacher;
  6. public String getName() {
  7. return name;
  8. }
  9. public void setName(String name) {
  10. this.name = name;
  11. }
  12. public int getAge() {
  13. return age;
  14. }
  15. public void setAge(int age) {
  16. this.age = age;
  17. }
  18. public Teacher getTeacher() {
  19. return teacher;
  20. }
  21. public void setTeacher(Teacher teacher) {
  22. this.teacher = teacher;
  23. }
  24. @Override
  25. public String toString() {
  26. return "Student [name=" + name + ", age=" + age + ", teacher=" + teacher + "]";
  27. }
  28.  
  29. }
  1. //Teacher类
  2. public class Teacher implements Serializable{
  3. private String name;
  4. private String classes;
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. public String getClasses() {
  12. return classes;
  13. }
  14. public void setClasses(String classes) {
  15. this.classes = classes;
  16. }
  17. @Override
  18. public String toString() {
  19. return "Teacher [name=" + name + ", classes=" + classes + "]";
  20. }
  21.  
  22. }

  第三步,也是最关键的一步,编写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

  代码如下:

  1. public class MyClassPathXmlApplicationContext {
  2. private String xmlName;
  3.  
  4. public MyClassPathXmlApplicationContext(String xmlName) {
  5. this.xmlName=xmlName;
  6. }
  7.  
  8. public Object getBean(String id) {
  9. Object obj=null; //声明引用.
  10. //进行xml的解析
  11. SAXReader reader=new SAXReader();
  12. try {
  13. Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(xmlName));
  14. Element root=document.getRootElement();
  15. //遍历.看是否有元素的id为传入的参数.
  16. List<Element> elements = root.elements();
  17. if(elements.size()>0) {
  18. for(Element element:elements ) {
  19. if(element.attributeValue("id").equals(id)) {//id相同开始创建对象
  20. //采用反射创建对象.
  21. String className=element.attributeValue("class");
  22. Class beanClass=Class.forName(className);
  23. obj=beanClass.newInstance();
  24. //获取子标签的属性.
  25. List<Element> attributes=element.elements();
  26. if(attributes.size()>0) {
  27. for(Element attribute:attributes) {
  28. String name=attribute.attributeValue("name");
  29. Field field = beanClass.getDeclaredField(name);
  30. field.setAccessible(true);
  31. if(attribute.attribute("ref")!=null) {
  32. //此属性的值是一个对象.这里由于直接调用getBean方法赋值给对象,返回的对象一定是Bean参数的对象,因此强制转换不会出问题
  33. String refid=attribute.attributeValue("ref");
  34. field.set(obj, getBean(refid));
  35. }
  36. else {
  37. //此属性值是一个字符串.这里单独处理int,float类型变量.如果不处理,会将String类型直接赋值给int类型,发生ClassCastException
  38. String value=attribute.attributeValue("value");
  39. //需要对类型进行判断
  40. if(value.matches("[0-9]+")) {
  41. //整数
  42. int x=Integer.parseInt(value);
  43. field.set(obj, x);
  44. continue;
  45. }
  46. if(value.matches("[0-9]*(\\.+)[0-9]*")) {
  47. //浮点数
  48. float y=Float.parseFloat(value);
  49. field.set(obj, y); //注意double可以接受float类型
  50. continue;
  51. }
  52. field.set(obj, value);//处理String类型
  53. }
  54. }
  55. }
  56. }
  57. }
  58. }
  59. } catch (Exception e) {
  60. e.printStackTrace();
  61. }
  62. return obj;
  63. }
  64. }

  第四步:测试.

  1. @Test
  2. public void testMySpring() {
  3. MyClassPathXmlApplicationContext applicationContext=new MyClassPathXmlApplicationContext("applicationContext.xml");
  4. System.out.println(applicationContext.getBean("student1"));
  5. }

  测试结果:

  1. Student [name=hlhdidi, age=13, teacher=Teacher [name=cwb, classes=高三九班]]

  总结:

  dom4j是一个很好的解析xml的工具,而解析xml是一个很重要的基本功,对于理解框架原理有很大的帮助.反射结合xml文件的解析,可以实现在任何类中方便的创建任何对象.

采用dom4j和反射模拟Spring框架的依赖注入功能的更多相关文章

  1. spring框架之依赖注入(DI)

    1. IOC和DI的概念 * IOC -- Inverse of Control,控制反转,将对象的创建权反转给Spring!! * DI -- Dependency Injection,依赖注入,在 ...

  2. PHP 从另一个角度来分析 Laravel 框架的依赖注入功能

    从根本上说,依赖注入不是让对象创建一个依赖关系,也不是让工厂对象去创建对象,而是将所需的依赖变成一个外部对象,使之成为一个"某些人的问题” 你为"某些人的问题”注入了类的依赖关系. ...

  3. Spring框架——IOC依赖注入

    本来想把IOC和AOP一起介绍的,但是AOP内容太多了,所以就分开了,最后的结果就是这一篇只剩下一点点了.这不是第一次写关于IOC的文章了,之前写过Java反射,Java注解,也写过通过XML解析实现 ...

  4. Spring框架(依赖注入)

    特点 1轻量级和侵入性低 2依赖注入和面向接口实现松耦合 3面向切面编程 减少样式代码 专有名词: 1依赖注入:对象无需自行管理依赖关系.通过系统负责协调在创建对象的第三方组件的设定,实现依赖关系自动 ...

  5. Spring框架的IOC核心功能快速入门

    2. 步骤一:下载Spring框架的开发包 * 官网:http://spring.io/ * 下载地址:http://repo.springsource.org/libs-release-local/ ...

  6. JavaEE开发之Spring中的依赖注入与AOP

    上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...

  7. JavaEE开发之Spring中的依赖注入与AOP编程

    上篇博客我们系统的聊了<JavaEE开发之基于Eclipse的环境搭建以及Maven Web App的创建>,并在之前的博客中我们聊了依赖注入的相关东西,并且使用Objective-C的R ...

  8. [ASP.NET Core 3框架揭秘] 依赖注入[8]:服务实例的生命周期

    生命周期决定了IServiceProvider对象采用怎样的方式提供和释放服务实例.虽然不同版本的依赖注入框架针对服务实例的生命周期管理采用了不同的实现,但总的来说原理还是类似的.在我们提供的依赖注入 ...

  9. [ASP.NET Core 3框架揭秘] 依赖注入[9]:实现概述

    <服务注册>.<服务消费>和<生命周期>主要从实现原理的角度对.NET Core的依赖注入框架进行了介绍,接下来更进一步,看看该框架的总体设计和实现.在过去的多个版 ...

随机推荐

  1. redis 五种数据类型的使用场景

    String 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...

  2. Dev统计选中行、如需其他数据源可留言

    Clipboard.Clear(); Dictionary<string, decimal> dtary = new Dictionary<string, decimal>() ...

  3. 随手编程---快速排序(QuickSort)-Java实现

    背景 快速排序,是在上世纪60年代,由美国人东尼·霍尔提出的一种排序方法.这种排序方式,在当时已经是非常快的一种排序了.因此在命名上,才将之称为"快速排序".这个算法是二十世纪的七 ...

  4. C#先序遍历2叉树(非递归)

    找了下先序遍历二叉树C# 实现貌似没有 顺手些了一个 大致思路是: 传入根节点,然后依次循环其子节点推入到栈中, 当推入的节点没有子节点的时候(叶子)或者所有子节点均已经遍历过后(上一次遍历的节点是该 ...

  5. UEFI Bootable USB Flash Drive - Create in Windows(WIN7 WIN8)

    How to Create a Bootable UEFI USB Flash Drive for Installing Windows 7, Windows 8, or Windows 8.1 In ...

  6. 转:django 接收页面form的post数组

    <input type="text" name="input[]"> <input type="text" name=&q ...

  7. Dynamics AX 2012 R2 AIF 内部异常 output session was auto-closes

    今天调用AIF出现异常,异常信息如下 This chanel can no longer be used to send message as the output session was auto- ...

  8. Bash:-:-通过while和shift判断脚本位置参数格式是否合法

    ]];then echo "请输入2个位置参数..." exit else num=$# ));do case ${num} in ) if ! echo "${1}&q ...

  9. 关于yuv格式

    首先,内存分布        1:YUV420          (1):I420:              YYYYYYYY UU VV    =>YUV420P          (2): ...

  10. 用Excel创建SQL server性能报告

    转载自Kun Lee "Creating SQL Server performance based reports using Excel" 性能测试调优中对数据库的监控十分重要, ...