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的实现。

最新文章

  1. 书中的银行,我们一起奋斗的C#,只因乐在其中~
  2. 腾讯优测-优社区干货精选 | &#160;那些年,我们在Android机型适配上遇到的坑之Camera拍照时快门咔嚓声
  3. 一个简单的scrapy爬虫抓取豆瓣刘亦菲的图片地址
  4. Linux物理内存相关数据结构
  5. 系统数据文件和信息之附加组ID
  6. fullcalendar日历控件集合知识
  7. js小功能合集:计算指定时间距今多久、评论树核心代码、字符串替换和去除。
  8. HUST 1541 Student’s question
  9. 【原创】大数据基础之Mesos(1)简介、安装、使用
  10. mount命令和自动挂载实例
  11. js中对象和对象创建方法
  12. playbook role应用
  13. 最简单的设计模式——单例模式的演进和推荐写法(Java 版)
  14. vscode快捷键的中文版
  15. HTML命名规范
  16. 安卓开发 1配置环境 (JDK+Andriod stiuio)
  17. Java设计模拟菜单
  18. Windows,远程计算机:X.X.X.X,这可能是由于CredSSP加密Oracle修正
  19. Django中的路由配置简介
  20. su: cannot set user id: Resource temporarily unavailable问题解决

热门文章

  1. c/c++常用代码--string trim
  2. 阅读verilog程序总结
  3. mvc5引用ExtJS6
  4. “我爱淘”冲刺阶段Scrum站立会议6
  5. background-clip
  6. ffmpeg 命令
  7. Spring MVC 环境搭建(二)
  8. hdu 3068 最长回文 manacher
  9. vs2008 添加与修改模板.
  10. google大赛 入围赛250分真题