1.简介

依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念。

2.案例

1)一般情况下的类耦合

Main.java

  1. public class Main {
  2. public static void main(String[] args) {
  3. /******** 一般写法,Main类与Chinese类和American类之间的强耦合 ***********/
  4. // Chinese和American,当类和方法修改时,此处的类和方法也需要修改
  5. Chinese chinese = new Chinese();
  6. chinese.sayHelloWorld("张三");
  7.  
  8. American american = new American();
  9. american.sayHelloWorld("Jack");
  10. }
  11. }
  12.  
  13. /******************** 一般方法 ***************************/
  14.  
  15. interface Human {
  16. public void sayHelloWorld(String name);
  17. }
  18.  
  19. class Chinese implements Human {
  20. public void sayHelloWorld(String name) {
  21. String helloWorld = "你好," + name;
  22. System.out.println(helloWorld);
  23. }
  24. }
  25.  
  26. class American implements Human {
  27. public void sayHelloWorld(String name) {
  28. String helloWorld = "Hello," + name;
  29. System.out.println(helloWorld);
  30. }
  31. }

通过上面代码可以看出:Main类与Chinese类和American类之间存在着强耦合 , Chinese和American类和方法修改时,此处的类和方法也需要修改。不容易扩展和维护。

2)工厂方法来解耦合

  1. public class Main {
  2. public static void main(String[] args) {
  3. /******** 工厂方法, Main类与类Chinese和American不再耦合,仅仅和其接口Human耦合 ***********/
  4. // 修改时还需要修改在Main类中修改这些字符串
  5. // Chinese和American,当类和方法修改时,只有方法需要修改
  6. HumanFactory humanFactory = new HumanFactory();
  7. Human human1 = humanFactory.getHuman("chinese");
  8. human1.sayHelloWorld("张三");
  9.  
  10. Human human2 = humanFactory.getHuman("american");
  11. human2.sayHelloWorld("Jack");
  12. }
  13. }
  14.  
  15. /******************** 工厂方法 ***************************/
  16. interface Human {
  17. public void sayHelloWorld(String name);
  18. }
  19.  
  20. class HumanFactory {
  21. public Human getHuman(String type) {
  22. if ("chinese".equals(type)) {
  23. return new Chinese();
  24. } else {
  25. return new American();
  26. }
  27. }
  28. }

通过上面代码可以看出:Main类与类Chinese和American不再耦合,仅仅和其接口Human耦合,修改时还需要修改在Main类中修改这些字符串,当类和方法修改时,只有方法需要修改。这一定程度上降低了Main类和Chinese、American类的耦合

3)依赖注入和控制反转

  1. public class Main {
  2. public static void main(String[] args) {
  3. /******************** IOC控制反转和依赖注入 ***************************/
  4. // 利用容器,通过xml文件直接注入属性值,在Main类中只添加需要的
  5. // Chinese和American,当类和方法修改时,代码完全不用修改,只需要修改xml文件即可,彻底实现了解耦
  6. BeanFactory beanFactory = new BeanFactory();
  7. beanFactory.init("/config.xml");
  8. UserBean userBean = (UserBean) beanFactory.getBean("userBean");
  9. System.out.println("userName=" + userBean.getUserName());
  10. System.out.println("password=" + userBean.getPassword());
  11. }
  12. }
  13.  
  14. /******************** IOC控制反转和依赖注入 ***************************/
  15. // 下面是Spring的IOC实现:Bean工厂
  16. class BeanFactory {
  17. private Map<String, Object> beanMap = new HashMap<String, Object>();
  18.  
  19. public void init(String fileName) {
  20. try {
  21. // 读取指定的配置文件
  22. SAXReader reader = new SAXReader();
  23. // System.out.println(xmlpath);
  24. String realPathString = new File("").getCanonicalPath();
  25. Document document = reader.read(new File(realPathString + "/src/com/devin/") + fileName);
  26. Element root = document.getRootElement();
  27. Element foo;
  28. // 遍历bean
  29. for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
  30. foo = (Element) i.next();
  31. // 获取bean的属性id和class
  32. Attribute id = foo.attribute("id");
  33. Attribute cls = foo.attribute("class");
  34. // 利用Java反射机制,通过class的名称获取Class对象
  35. Class bean = Class.forName(cls.getText());
  36. // 获取对应class的信息
  37. java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
  38. // 获取其属性描述
  39. java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
  40. // 设置值的方法
  41. Method mSet = null;
  42. // 创建一个对象
  43. Object obj = bean.newInstance();
  44. // 遍历该bean的property属性
  45. for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {
  46. Element foo2 = (Element) ite.next();
  47. // 获取该property的name属性
  48. Attribute name = foo2.attribute("name");
  49. String value = null;
  50. // 获取该property的子元素value的值
  51. for (Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
  52. Element node = (Element) ite1.next();
  53. value = node.getText();
  54. break;
  55. }
  56. for (int k = 0; k < pd.length; k++) {
  57. if (pd[k].getName().equalsIgnoreCase(name.getText())) {
  58. mSet = pd[k].getWriteMethod();
  59. mSet.invoke(obj, value);
  60. }
  61. }
  62. }
  63.  
  64. // 将对象放入beanMap中,其中key为id值,value为对象
  65. beanMap.put(id.getText(), obj);
  66. }
  67. } catch (Exception e) {
  68. System.out.println(e.toString());
  69. }
  70. }
  71.  
  72. // 通过bean的id获取bean的对象.
  73. public Object getBean(String beanName) {
  74. Object obj = beanMap.get(beanName);
  75. return obj;
  76. }
  77. }
  78.  
  79. UserBean.java
  80.  
  81. public class UserBean {
  82. private String userName;
  83. private String password;
  84.  
  85. public String getPassword() {
  86. return password;
  87. }
  88.  
  89. public String getUserName() {
  90. return userName;
  91. }
  92.  
  93. public void setUserName(String userName) {
  94. this.userName = userName;
  95. }
  96.  
  97. public void setPassword(String password) {
  98. this.password = password;
  99. }
  100. }
  101.  
  102. config.xml
  103.  
  104. <?xml version="1.0" encoding="UTF-8"?>
  105. <beans>
  106. <bean id="userBean" class="com.devin.UserBean">
  107. <property name="userName">
  108. <value>张三</value>
  109. </property>
  110. <property name="password">
  111. <value>Jack</value>
  112. </property>
  113. </bean>
  114. </beans>
  1. 说明:模拟了SpringIOC的实现,虽然只是完成了Spring中依赖注入的一小部分工作,但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现。

Java之控制反转和依赖注入的更多相关文章

  1. Java 控制反转和依赖注入模式【翻译】【整理】

    Inversion of Control Containers and the Dependency Injection pattern --Martin Fowler 本文内容 Component ...

  2. java控制反转与依赖注入

    1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ...

  3. Java Web实现IOC控制反转之依赖注入

    控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注入 ...

  4. java依赖的斗争:依赖倒置、控制反转和依赖注入

    控制反转(Inversion Of Controller)的一个著名的同义原则是由Robert C.Martin提出的依赖倒置原则(Dependency Inversion Principle),它的 ...

  5. 轻松了解Spring中的控制反转和依赖注入(二)

    紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ...

  6. spring学习总结一----控制反转与依赖注入

    spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转 ...

  7. spring 控制反转与依赖注入原理-学习笔记

    在Spring中有两个非常重要的概念,控制反转和依赖注入:控制反转将依赖对象的创建和管理交由Spring容器,而依赖注入则是在控制反转的基础上将Spring容器管理的依赖对象注入到应用之中: 所谓依赖 ...

  8. spring(3)------控制反转(IOC)/依赖注入(DI)

    一.spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control).它把传统上由程序代码直接操控的对象的调用权交给容器.通过容器来实现对象组件的装配和管理. 所谓 ...

  9. 【Spring Framework】Spring 入门教程(一)控制反转和依赖注入

    参考资料 Spring 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...

随机推荐

  1. SOAPUI使用教程-REST服务和WADL

    首先创建一个新的REST项目: 选择文件|新建项目REST从主菜单: 通常情况下,我们可能会只提供一个URI 点击导入消耗. 在新建项目消耗对话框: 点击浏览. 然后,我们可以浏览到该文件: 点击   ...

  2. Ubuntu13.10下安装HADOOP

    2013-03-05 09:04 995人阅读 评论(0) 收藏 举报 运行这个脚本: #/bin/sh sudo add-apt-repository ppa:webupd8team/java su ...

  3. Print a Binary Tree in Vertical Order

    http://www.geeksforgeeks.org/print-binary-tree-vertical-order/ package algorithms; import java.util. ...

  4. WP8解析JSON格式(使用DataContractJsonSerializer类)(推荐)

    DataContractJsonSerializer是.NET自带的类,在解析JSON格式的时候使用起来方便快捷,至于生成方面由于暂时没用到就没去看了.使用需要引用System.Runtime.Ser ...

  5. CentOS 7 学习笔记(二)systemd

    sysVinit启动原理在我们打开Linux电脑的电源后第一个启动的进程就是init.分配给init进程的PID是1.它是系统其他所有进程的父进程.当一台Linux电脑启动后,处理器会先在系统存储中查 ...

  6. JS /JQuery 获取变量为数字时 容易出错 可能不是数字类型

    Javascript内置函数,原型为parseInt ( String s , [ int radix ] ),用于解析一个字符串,并返回一个整数. var $prod_kucun=$(this).n ...

  7. php中echo(),print(),print_r(),var_dump()间的区别

    echo()函数:输出一个或多个字符串.实际上它并不是一个函数,所以不必对它使用括号,直接用echo就行.然而,如果您希望向echo()传递一个以上的参数,使用括号将会生成解析错误.echo()函数比 ...

  8. 浏览器地址栏输入一个URL后回车,将会发生的事情

    浏览器向DNS服务器查找输入URL对应的IP地址. DNS服务器返回网站的IP地址. 浏览器根据IP地址与目标web服务器在80端口上建立TCP连接 浏览器获取请求页面的html代码. 浏览器在显示窗 ...

  9. 一个基于jQuery的移动端条件选择查询插件(原创)

    下载插件 目前给出的下载是混淆了后的代码 愿意一起探讨的可以找我要源码 使用方式: var ConditionsChoose = $("#Screening").Condition ...

  10. IOAPIC重定位中断处理函数思路整理

    因为小可并非硬件编程出身,汇编基础又比较差...所以刚开始理解利用IOAPIC重定位技术的时候相当困难. 何为IOAPIC? 首先,必须认识到它是一个硬件,可编程的硬件.我理解的它在整个流程中的作用如 ...