Java之控制反转和依赖注入
1.简介
依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念。
2.案例
1)一般情况下的类耦合
Main.java
public class Main {
     public static void main(String[] args) {
          /******** 一般写法,Main类与Chinese类和American类之间的强耦合 ***********/
          // Chinese和American,当类和方法修改时,此处的类和方法也需要修改
          Chinese chinese = new Chinese();
          chinese.sayHelloWorld("张三");
          American american = new American();
          american.sayHelloWorld("Jack");
     }
}
/******************** 一般方法 ***************************/
interface Human {
     public void sayHelloWorld(String name);
}
class Chinese implements Human {
     public void sayHelloWorld(String name) {
          String helloWorld = "你好," + name;
          System.out.println(helloWorld);
     }
}
class American implements Human {
     public void sayHelloWorld(String name) {
          String helloWorld = "Hello," + name;
          System.out.println(helloWorld);
     }
}
通过上面代码可以看出:Main类与Chinese类和American类之间存在着强耦合 , Chinese和American类和方法修改时,此处的类和方法也需要修改。不容易扩展和维护。
2)工厂方法来解耦合
public class Main {
     public static void main(String[] args) {
          /******** 工厂方法, Main类与类Chinese和American不再耦合,仅仅和其接口Human耦合 ***********/
          // 修改时还需要修改在Main类中修改这些字符串
          // Chinese和American,当类和方法修改时,只有方法需要修改
          HumanFactory humanFactory = new HumanFactory();
          Human human1 = humanFactory.getHuman("chinese");
          human1.sayHelloWorld("张三");
          Human human2 = humanFactory.getHuman("american");
          human2.sayHelloWorld("Jack");
     }
}
/******************** 工厂方法 ***************************/
interface Human {
     public void sayHelloWorld(String name);
}
class HumanFactory {
     public Human getHuman(String type) {
          if ("chinese".equals(type)) {
               return new Chinese();
          } else {
               return new American();
          }
     }
}
通过上面代码可以看出:Main类与类Chinese和American不再耦合,仅仅和其接口Human耦合,修改时还需要修改在Main类中修改这些字符串,当类和方法修改时,只有方法需要修改。这一定程度上降低了Main类和Chinese、American类的耦合
3)依赖注入和控制反转
public class Main {
     public static void main(String[] args) {
          /******************** IOC控制反转和依赖注入 ***************************/
          // 利用容器,通过xml文件直接注入属性值,在Main类中只添加需要的
          // Chinese和American,当类和方法修改时,代码完全不用修改,只需要修改xml文件即可,彻底实现了解耦
          BeanFactory beanFactory = new BeanFactory();
          beanFactory.init("/config.xml");
          UserBean userBean = (UserBean) beanFactory.getBean("userBean");
          System.out.println("userName=" + userBean.getUserName());
          System.out.println("password=" + userBean.getPassword());
     }
}
/******************** IOC控制反转和依赖注入 ***************************/
// 下面是Spring的IOC实现:Bean工厂
class BeanFactory {
     private Map<String, Object> beanMap = new HashMap<String, Object>();
     public void init(String fileName) {
          try {
               // 读取指定的配置文件
               SAXReader reader = new SAXReader();
               // System.out.println(xmlpath);
               String realPathString = new File("").getCanonicalPath();
               Document document = reader.read(new File(realPathString + "/src/com/devin/") + fileName);
               Element root = document.getRootElement();
               Element foo;
               // 遍历bean
               for (Iterator i = root.elementIterator("bean"); i.hasNext();) {
                    foo = (Element) i.next();
                    // 获取bean的属性id和class
                    Attribute id = foo.attribute("id");
                    Attribute cls = foo.attribute("class");
                    // 利用Java反射机制,通过class的名称获取Class对象
                    Class bean = Class.forName(cls.getText());
                    // 获取对应class的信息
                    java.beans.BeanInfo info = java.beans.Introspector.getBeanInfo(bean);
                    // 获取其属性描述
                    java.beans.PropertyDescriptor pd[] = info.getPropertyDescriptors();
                    // 设置值的方法
                    Method mSet = null;
                    // 创建一个对象
                    Object obj = bean.newInstance();
                    // 遍历该bean的property属性
                    for (Iterator ite = foo.elementIterator("property"); ite.hasNext();) {
                         Element foo2 = (Element) ite.next();
                         // 获取该property的name属性
                         Attribute name = foo2.attribute("name");
                         String value = null;
                         // 获取该property的子元素value的值
                         for (Iterator ite1 = foo2.elementIterator("value"); ite1.hasNext();) {
                              Element node = (Element) ite1.next();
                              value = node.getText();
                              break;
                         }
                         for (int k = 0; k < pd.length; k++) {
                              if (pd[k].getName().equalsIgnoreCase(name.getText())) {
                                   mSet = pd[k].getWriteMethod();
                                   mSet.invoke(obj, value);
                              }
                         }
                    }
                    // 将对象放入beanMap中,其中key为id值,value为对象
                    beanMap.put(id.getText(), obj);
               }
          } catch (Exception e) {
               System.out.println(e.toString());
          }
     }
     // 通过bean的id获取bean的对象.
     public Object getBean(String beanName) {
          Object obj = beanMap.get(beanName);
          return obj;
     }
}
UserBean.java
public class UserBean {
     private String userName;
     private String password;
     public String getPassword() {
          return password;
     }
     public String getUserName() {
          return userName;
     }
     public void setUserName(String userName) {
          this.userName = userName;
     }
     public void setPassword(String password) {
          this.password = password;
     }
}
config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
     <bean id="userBean" class="com.devin.UserBean">
          <property name="userName">
               <value>张三</value>
          </property>
          <property name="password">
               <value>Jack</value>
          </property>
     </bean>
</beans>
说明:模拟了Spring中IOC的实现,虽然只是完成了Spring中依赖注入的一小部分工作,但是很好的展现了Java反射机制在Spring中的应用,能使我们能更好的从原理上了解IOC的实现。
Java之控制反转和依赖注入的更多相关文章
- Java 控制反转和依赖注入模式【翻译】【整理】
		Inversion of Control Containers and the Dependency Injection pattern --Martin Fowler 本文内容 Component ... 
- java控制反转与依赖注入
		1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public clas ... 
- Java Web实现IOC控制反转之依赖注入
		控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题,也是轻量级的Spring框架的核心. 控制反转一般分为两种类型,依赖注入 ... 
- java依赖的斗争:依赖倒置、控制反转和依赖注入
		控制反转(Inversion Of Controller)的一个著名的同义原则是由Robert C.Martin提出的依赖倒置原则(Dependency Inversion Principle),它的 ... 
- 轻松了解Spring中的控制反转和依赖注入(二)
		紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类 ... 
- spring学习总结一----控制反转与依赖注入
		spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转 ... 
- spring 控制反转与依赖注入原理-学习笔记
		在Spring中有两个非常重要的概念,控制反转和依赖注入:控制反转将依赖对象的创建和管理交由Spring容器,而依赖注入则是在控制反转的基础上将Spring容器管理的依赖对象注入到应用之中: 所谓依赖 ... 
- spring(3)------控制反转(IOC)/依赖注入(DI)
		一.spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control).它把传统上由程序代码直接操控的对象的调用权交给容器.通过容器来实现对象组件的装配和管理. 所谓 ... 
- 【Spring Framework】Spring 入门教程(一)控制反转和依赖注入
		参考资料 Spring 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ... 
随机推荐
- Linux内核补丁批量自动下载工具
			Linux kernel官网cgit工具不支持按变更代码进行补丁搜索,想到个办法就是把补丁都抓下来,这样可以在本地搜索.花了2个小时写了个小工具,话不多说,直接看效果: E:\docs\TOOLS\p ... 
- linux下的tcp连接超时
			最近需要写一个linux下的通信程序, 通信模块用的是Qt的QTcpSocket. 最后程序需要增加一个断网检测, 在windows下调试没问题, 拔网线, 断网口都能马上检测到, 但到了部署到lin ... 
- 简单C#、asp.net mvc验证码的实现
			using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Text;u ... 
- centos 6.5 升级内核 linux 3.12.17 (笔记 实测)
			环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G) 系统版本:Linux centos 2.6.32-431.el6.x86_64(Centos-6.5-x86_64-mi ... 
- css屏蔽元素的鼠标事件pointer-events
			// 屏蔽点击 $('body').css('pointer-events', 'none'); //恢复默认 $('body').css('pointer-events', 'auto'); 用 ... 
- 安装OS X虚拟机错误vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1123
			新建一个虚拟机, 选择客户机操作系统为Apple MacOS X 10.10, 其余参数可以默认. 注意建好之后不要急着打开客户机, 因为直接打开你会发现新建的客户机将会无法启动. 仔细阅读Mac O ... 
- 5.Powershell变量
			在指令执行过程中,会有一些数据产生,这些数据被用于以后的语句,需要一个存储单元暂时的存放这些数据,这个时候定义一个变量来存储数据.例如$string = “Hello Powershell!” Pow ... 
- 基于AT89C51单片机的贪吃蛇电子游戏(仿真)
			有关贪吃蛇的历史发展可以看一下这个网址,贪吃蛇最初的设计和现在并不相同..http://www.techweb.com.cn/internet/2013-02-21/1278055.shtml 该项目 ... 
- 一个哥们看到数据库日志不断增大 [log_reuse_wait_desc]为replication 之后的做法
			一哥们看到数据库日志不断增大 [log_reuse_wait_desc]为replication 之后的做法 一天那个哥们看到数据库日志暴涨,用sys.databases 视图看一下[log_reus ... 
- [译]MVC网站教程(二):异常管理
			介绍 “MVC网站教程”系列的目的是教你如何使用 ASP.NET MVC 创建一个基本的.可扩展的网站. 1) MVC网站教程(一):多语言网站框架 2) MVC网站教程(二):异常管理 3) ... 
