學習java的同學注意了!!! 學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:523047986 我們一起學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.javapublic 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學習交流群,群號碼:523047986 我們一起學Java!
新聞熱點
疑難解答