Java之控制反轉和依賴注入

1.簡介java

依賴注入和控制反轉,目的是爲了使類與類之間解耦合,提升系統的可擴展性和可維護性,下面經過一個例子來引入這一律念。node

 

2.案例this

1)通常狀況下的類耦合spa

Main.javacode

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類和方法修改時,此處的類和方法也須要修改。不容易擴展和維護。xml

 

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類的耦合blog

 

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的實現。
相關文章
相關標籤/搜索