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

时间: 2024-11-08 07:09:47

java控制反转与依赖注入的相关文章

java 控制反转和依赖注入的理解

开始好好学习java基础和思想~ 控制反转(IOC)是Spring框架的核心思想,用我自己的话说,就是你要做一件事,别自己可劲new了,你就说你要干啥,然后外包出去就好~ 依赖注入(DI) 在我浅薄的想法中,就是通过接口的引用和构造方法的表达,将一些事情整好了反过来传给需要用到的地方~ 这样做得好处:做到了单一职责,并且提高了复用性,解耦了之后,任你如何实现,使用接口的引用调用的方法,永远不需要改变 举一个栗子: 写个接口,说咱们购物去~ public interface IShopping {

java控制反转及依赖注入

先来看看控制反转的基本含义: 控制反转(IOC)模式(又称DI:Dependency Injection)就是Inversion of Control,控制反转.在Java开发中,IoC意 味着将你设计好的类交给系统去控制,而不是在你的类内部控制.这称为控制反转.换句话说,就是将创建管理对象的工作交给容器来做. 传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象:而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建:谁控制谁?当然是

Java之控制反转和依赖注入

1.简介 依赖注入和控制反转,目的是为了使类与类之间解耦合,提高系统的可扩展性和可维护性,下面通过一个例子来引入这一概念. 2.案例 1)一般情况下的类耦合 Main.java public class Main { public static void main(String[] args) { /******** 一般写法,Main类与Chinese类和American类之间的强耦合 ***********/ // Chinese和American,当类和方法修改时,此处的类和方法也需要修改

控制反转与依赖注入

关于控制反转和依赖注入的文章和书籍很多,对其定义也解释的也仁者见仁,这里就不赘述了,这是本人(只代表个人观点)理解之后用通俗的例子和平淡的话词为您解释,希望对您有所帮助: 控制反转(IoC/Inverse Of Control):   调用者不再创建被调用者的实例,由spring框架实现(容器创建)所以称为控制反转. 依赖注入(DI/Dependence injection) :   容器创建好实例后再注入调用者称为依赖注入. 当 某个角色(可能是一个Java实例,调用者)需要另一个角色(另一个

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

一,spring核心概念理解 控制反转: 控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理. 所谓的"控制反转"概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器. 没有控制反转这种模式前,你创建一个对象,在什么地方用,你得单独通过关键字new出来用, 但现在可以不用这样,你把new对象的权利交给spring配置文件,通过配置文件来'new', 就是权利的反转,你以前干的事

控制反转和依赖注入(转)

1.控制反转(Inversion of Control)与依赖注入(Dependency Injection) 控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理.所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器. IoC是一个很大的概念,可以用不同的方式来实现.其主要实现方式有两种:<1>依赖查找(Dependency Lookup):容器提供回调接口和上下文环

[转]第二章 控制反转和依赖注入

Spring.Net 中提供了很多功能,比如依赖注入,面向切面编程(AOP),数据访问抽象以及ASP.Net扩展等等的功能.而其中最核心的功能就是依赖注入(Dependency Injection),而使用依赖注入带来的最大好处就是能够通过它降低应用程序中对象与对象之间的耦合. 控制反转(Inversion of Control)和 依赖注入(Dependency Injection),他们的英文缩写分别是IOC和DI,其实它们是同一个概念的不同角度的描述,由于控制反转概念比较模糊(可能只是理解

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

spring作为java EE中使用最为广泛的框架,它的设计体现了很多设计模式中经典的原则和思想,所以,该框架的各种实现方法非常值得我们去研究,下面先对spring中最为重要的思想之一----控制反转(依赖注入)进行简单的总结. 一.控制反转与依赖注入的概念 在学习spring框架的时候,我们习惯性地将控制反转和依赖注入放在一起,其实,两者体现的思想原则都是差不多的,只不过控制反转是一种更广泛的程序操作理念,而依赖注入是一种更为具体的实现方法,总的来说,控制反转可以依靠依赖注入来实现. 1.控制

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

紧接上一篇文章<轻松了解Spring中的控制反转和依赖注入>讲解了SpringIOC和DI的基本概念,这篇文章我们模拟一下SpringIOC的工作机制,使我们更加深刻的理解其中的工作. 类之间的结构图如下 以下是代码 BeanFactor接口:在Spring源码中的定义是:持有对一定数量的Bean的定义,同时每个Bean都被唯一标识的对象(类),需要实现这个接口.根据对Bean的定义,该工厂将会返回一个包含Bean定义的对象的独立实例(原型设计模式),或者单例共享(一个不错的单例设计模式,)范