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 教程 说在前面 什么样的架构,我们认为是一个优秀的架构? 判断准则:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:在不断添加新的代码的同时,可以不修改原有代码,即符合 ...
随机推荐
- 【原】iOS学习之Quartz2D(1)
什么是Quartz2D 1.Quartz 2D 是一个二维绘图引擎,同时支持iOS和Mac系统 2.Quartz 2D 能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成 ...
- 【转】iOS学习之translucent属性
原文地址:http://www.jianshu.com/p/930643270455 总所周知,苹果从iOS7开始采用扁平化的界面风格,颠覆了果粉们"迷恋"的拟物化风格.对于开发者 ...
- css 简析folat
1.float?? 不知道大家是否还记得之前我们讲过页面是文档流,具体什么是文档流,我就不说了?于是我们页面布局如果用div的话,那么块状的元素是怎么排列的,什么叫块状自己去看? 如果我们呢用div布 ...
- 深入理解JavaScript中 fn() 和 return fn() 的区别
在js中,经常会遇到在函数里调用其它函数的情况,这时候会有 fn() 这种调用方式,还有一种是 return fn() 这种调用方式,一些初学者经常会一脸萌逼地被这两种方式给绕晕了.这里用一个优雅的面 ...
- C# winform安装部署(转载)
c# winform 程序打包部署 核心总结: 1.建议在完成的要打包的项目外,另建解决方案建立安装部署项目(而不是在同一个解决方案内新建),在解决方案上右击-〉添加-〉现有项目-〉选择你要打包的项目 ...
- 实验mongodb使用gridfs存放一个大文件
1.启动mongoDB 2.使用gridfs存放大文件 3.观察fs.chunks和fs.files的情况 命令 db.fs.chunks.find()查到的是一些二进制文件:
- JavaScript鼠标经过图片的放大镜效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- spring的代理模式
静态代理: 首先定义一个接口,随便写一个方法 定义2个实现接口的方法 (被代理的对象) (代理对象) 需要将接口 定义get set 方法 代理增强的方法 然后实现 输出结果如下: 动态代理(jdk动 ...
- Ajax全面基础学习(一)
快捷方法: $.get(url,[data],[callback],[type])get方法的[data]将被链在url后面[callback]是请求成功后的回调,可以得到响应数据,如果请求失败,看不 ...
- Your awesome titleHH
Welcome to Jekyll! Your awesome titleHH About Blogging Like a Hacker Welcome to Jekyll! Jan 9, 2016 ...