日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

解析Spring IOC原理——工厂模式与反射机制的综合应用

發布時間:2025/6/15 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解析Spring IOC原理——工厂模式与反射机制的综合应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
(一)工廠模式

從一個例子開始講起:

首先我們建立一個Chinese.java類,該類的sayHelloWorld(String name)方法,用中文對名為name的人問好,其內容如下:

?????

[java]?view plaincopyprint?
  • public?class?Chinese?{??
  • ????/**--?用中文對某人問好.?--*/??
  • ????publicvoid?sayHelloWorld(String?name)?{??
  • ???????String?helloWorld?=?"你好,"?+?name;??
  • ???????System.out.println(helloWorld);??
  • ????}??
  • }??
  • ?

    下面我們接著建立一個American.java類,該類的sayHelloWorld(String name)方法,用英文對名為name的人問好,其內容如下:下面我們接著建立一個American.java類,該類的sayHelloWorld(String name)方法,用英文對名為name的人問好,其內容如下:

    [html]?view plaincopyprint?
  • publicclass?American?{??
  • ??
  • ????/*--?用英文對某人問好?--*/??
  • ????publicvoid?sayHelloWorld(String?name)?{??
  • ???????String?helloWorld?=?"Hello,"?+?name;??
  • ???????System.out.println(helloWorld);??
  • ????}??
  • }??

  • ?最后我們編寫一個測試類對這兩個類的sayHelloWorld(String name)方法進行測試,下面是該類的內容:

    [java]?view plaincopyprint?
  • publicclass?HelloWorldTest?{??
  • ??
  • ????/*--?測試Chinese和American的sayHelloWorld()方法?--*/??
  • ????publicstaticvoid?main(String[]?args)?{??
  • ???????Chinese?chinese?=?new?Chinese();??
  • ???????chinese.sayHelloWorld("極度暴走");??
  • ?????????
  • ???????American?american?=?new?American();??
  • ???????american.sayHelloWorld("jidubaozou");??
  • ????}??
  • }??
  • ?

    現實生活中我們總是把同一類產品放在一個工廠中生產,消費者只需要告訴工廠自己需要這一類產品中的哪一種產品,工廠就能夠生產出對應的產品,從而完成交易。

    這里我們把上面例子中的HelloWorldTest類想象為消費者,而Chinese和American類想象為產品,根據上面的例子,我們可以看到每當HelloWorldTest這個消費者需要一個產品時都要去自己去生產(new),這樣消費者就不得不去了解各個產品的內部結構及生產過程。顯然對于消費者來說這樣是很麻煩的。

    而在程序設計領域中這個問題就叫做強耦合問題,HelloWorldTest類與ChineseAmerican這兩個類都存在強耦合關系。設想一下,如果程序中的很多類都需要用到ChineseAmerican類這兩個類,那么每個類就必須和這兩個類強耦合,而且現實的項目中類似于Chinese這種類往往不僅兩個,這樣會使得整個程序的耦合度很高,增大程序的復雜度。這時我們就想到,能否也使用一個工廠來生產這些類,這樣如果某個類需要用到工廠中的哪個類,就只要通過和工廠生產就行了,從而降低了整個程序的耦合度。

    下面看看工廠模式是如何實現的:

    首先建立接口類Human.java,其內容如下:

    [java]?view plaincopyprint?
  • public?interface?Human?{??
  • ??
  • ????/**?*//**?
  • ?????*?對某人問好.?
  • ?????*?@param?name?姓名?
  • ?????*/??
  • ????public?void?sayHelloWorld(String?name);??
  • }??
  • ?

    并將American.java類和Chinese.java類改為實現該接口,即類頭分別改成:public class American implements Humanpublic class Chinese implements Human

    接著編寫HumanFactory.java工廠類,其內容為

    ?

    [java]?view plaincopyprint?
  • public?class?HumanFactory?{??
  • ??
  • ???????/**?*//**?
  • ????????*?通過類型字段獲取人的相應實例?
  • ????????*?@param?type?類型?
  • ????????*?@return?返回相應實例?
  • ????????*/??
  • ???????public?Human?getHuman(String?type)?{??
  • ??????????????if?("chinese".equals(type))?{??
  • ?????????????????????return?new?Chinese();??
  • ??????????????}?else?{??
  • ?????????????????????return?new?American();??
  • ??????????????}??
  • ???????}??
  • }??
  • ?

    最后我們還需要修改測試類HelloWorld.java類,修改后的內容如下:?

    ?

    [java]?view plaincopyprint?
  • public?class?HelloWorldTest?{??
  • ??
  • ???????/**?*//**?
  • ????????*?測試sayHelloWorld()方法.?
  • ????????*?@param?args?
  • ????????*/??
  • ???????public?static?void?main(String[]?args)?{??
  • ??????????????HumanFactory?factory?=?new?HumanFactory();??
  • ??????????????Human?human1?=?factory.getHuman("chinese");??
  • ??????????????human1.sayHelloWorld("極度暴走");??
  • ??
  • ??????????????Human?human2?=?factory.getHuman("american");??
  • ??????????????human2.sayHelloWorld("jidubaozou");??
  • ??????????????}??
  • }??

  • 通過上面的例子可以看到,使用工廠模式實現的方式,?HelloWorldTest 不再與Chinese類和American類耦合,而只是和他們共同的接口耦合,從而很大程度的降低的程序的耦合性。到這里或許很多人會有一點疑慮,使用工廠模式的HelloWorldTest 類也是需要耦合兩個類(即HumanFactory 類和Human 接口)那么為什么能說降低耦合度呢,這就要是何時要使用工廠模式的問題了。假如類似于我們這個例子,HumanFactory 這個工廠只生產兩個類,那的確沒有什么必要使用工廠模式,但是現實的項目中往往有更多和Chinese類類似的類,比如English,Japanese,這時候就能體現出工廠模式的優勢了

    ?

    ?(二)Spring IOC的原理

    首先我們來講下為什么要引入IOC:

    假設上面舉例的那個程序已經部署到服務器中,并已經上線運行,這時項目來了這樣一個新需求:增加一個Japanese類,并且在HelloWorldTest 類中調用Japanese的sayHelloWorld方法。在沒有引入IOC之前,很顯然我們為了這個新需求,必須把項目停止下來,然后從新編譯HumanFactory 和HelloWorldTest這兩個類,最后再重新上線運行。

    而使用IOC,則能夠在不重新編譯部署的情況下實現上面的新需求!

    那么我們來看一下IOC是去怎么實現這個新需求的:?

    ?首先我們在com.human包內創建一個Japanese類:

    [java]?view plaincopyprint?
  • public?class?Japanese?implements?Human{??
  • ?????private?String?name;??
  • ?????private?String?age;??
  • ???????
  • ?????public?void?sayHelloWorld(String?string){??
  • ?????????System.out.println("你好,"+string);??
  • ?????}??
  • ?????public?String?getAge()?{??
  • ?????return?age;??
  • ?????}??
  • ?????public?void?setAge(String?age)?{??
  • ?????this.age?=?age;??
  • ?????}??
  • ?????public?String?getName()?{??
  • ?????return?name;??
  • ?????}??
  • ?????public?void?setName(String?name)?{??
  • ?????????this.name?=?name;??
  • ?????}??
  • }??

  • ?

    然后對HelloWorldTest 類做如下修改

    ?

    [java]?view plaincopyprint?
  • public?class?HelloWorldTest?{??
  • ??
  • ???????public?static?void?main(String[]?args)?{??
  • ?????????????ClassPathXmlApplicationContext?ctx?=?new?ClassPathXmlApplicationContext("beans.xml");??
  • ?????????????BeanFactory?beanFactory=ctx.getBeanFactory();??
  • ?????????????Human?human=beanFactory.getBean("human");??
  • ?????????????human.sayHelloWorld("極度暴走");??
  • ?????????????}??
  • }??
  • ?

    然后我們在beans.xml中做如下配置:

    [html]?view plaincopyprint?
  • <?xml?version="1.0"?encoding="UTF-8"?>??
  • ??
  • <beans>??
  • ????<bean?id="human"?class="com.human.Japanese">??
  • ???????<property?name="name">??
  • ???????????<value>漩渦鳴人</value>??
  • ???????</property>??
  • ???????<property?name="password">??
  • ???????????<value>22</value>??
  • ???????</property>??
  • <pre?class="html"?name="code"></bean>??
  • </beans></pre>??
  • <p><br>??
  • 這樣,HelloWorldTest?便會去調用Japanese類的sayHelloWorld()方法;用這種形式,我們只要修改beans.xml的配置便可以改變HelloWorldTest?類中human對象,并且不需要重新部署項目,這樣就實現了human對象的熱拔插。</p>??
  • <p>從上面的代碼可以看到spring?IOC的這種實現方式主要是靠BeanFactory這個類,那么這個BeanFactory到底有什么神奇之處呢?</p>??
  • <p>下面讓我們模擬實現一個BeanFactory:</p>??
  • <p><br>??
  • ?</p>??
  • <pre?class="java"?name="code">import?java.io.InputStream;??
  • import?java.lang.reflect.Method;??
  • import?java.util.HashMap;??
  • import?java.util.Iterator;??
  • import?java.util.Map;??
  • import?org.dom4j.Attribute;??
  • import?org.dom4j.Document;??
  • import?org.dom4j.Element;??
  • import?org.dom4j.io.SAXReader;??
  • ??
  • /**?*//**??
  • ?*?bean工廠類.??????
  • ?*/??
  • public?class?BeanFactory?{??
  • ???????private?Map<String,?Object>?beanMap?=?new?HashMap<String,?Object>();??
  • ??
  • ???????/**?*//**??
  • ????????*?bean工廠的初始化.??
  • ????????*?@param?xml?xml配置文件??
  • ????????*/??
  • ???????public?void?init(String?xml)?{??
  • ??????????????try?{??
  • ?????????????????????//讀取指定的配置文件??
  • ?????????????????????SAXReader?reader?=?new?SAXReader();??
  • ?????????????????????ClassLoader?classLoader?=?Thread.currentThread().getContextClassLoader();??
  • ?????????????????????//從class目錄下獲取指定的xml文件??
  • ?????????????????????InputStream?ins?=?classLoader.getResourceAsStream(xml);??
  • ?????????????????????Document?doc?=?reader.read(ins);??
  • ?????????????????????Element?root?=?doc.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();??
  • ???????????????????????????????????//利用Java的反射機制調用對象的某個set方法,并將值設進去??
  • ???????????????????????????????????mSet.invoke(obj,?value);??
  • }??
  • }??
  • }??
  • ??
  • //將對象放入beanMap中,其中key為id值,value為對象??
  • beanMap.put(id.getText(),?obj);??
  • }??
  • }?catch?(Exception?e)?{??
  • ????System.out.println(e.toString());??
  • }??
  • }??
  • ??
  • ???????/**?*//**??
  • ????????*?通過bean的id獲取bean的對象.??
  • ????????*?@param?beanName?bean的id??
  • ????????*?@return?返回對應對象??
  • ????????*/??
  • ???????public?Object?getBean(String?beanName)?{??
  • ??????????????Object?obj?=?beanMap.get(beanName);??
  • ??????????????return?obj;??
  • ???????}??
  • ??
  • ???????/**?*//**??
  • ????????*?測試方法.??
  • ????????*?@param?args??
  • ????????*/??
  • ???????public?static?void?main(String[]?args)?{??
  • ?????????????BeanFactory?factory?=?new?BeanFactory();??
  • ??????????????factory.init("bean.xml");??
  • ??????????????Human?human=?(Human)?factory.getBean("human");??
  • ??????????????human.sayHelloWorld("極度暴走");??
  • ??????????????System.out.println("Name="?+?human.getName());??
  • ??????????????System.out.println("age="?+?human.getAge());??
  • ???????}??
  • }??
  • </pre>??
  • <p><br>??
  • </p>??
  • <p>測試方法的執行結果:你好,極度暴走</p>??
  • <p>漩渦鳴人</p>??
  • <p>22</p>??
  • <p>?</p>??
  • <p>總結:從上面的代碼可以看出Spring的bean工廠主要實現了以下幾個步驟</p>??
  • <p>1.解析配置文件(bean.xml)</p>??
  • <p>2.使用反射機制動態加載每個class節點中配置的類</p>??
  • <p>3.為每個class節點中配置的類實例化一個對象</p>??
  • <p>4.使用反射機制調用各個對象的seter方法,將配置文件中的屬性值設置進對應的對象</p>??
  • <p>5.將這些對象放在一個存儲空間(beanMap)中</p>??
  • <p>6.使用getBean方法從存儲空間(beanMap)中取出指定的JavaBean</p>??
  • <p>?</p>??
  • <p>PS:IOC的標準定義:</p>??
  • <p>(Inversion?of?Control)?</p>??
  • <p>  中文譯為:?控制反轉</p>??
  • <p>  IOC的基本概念是:不創建對象,但是描述創建它們的方式。在代碼中不直接與對象和服務連接,但在配置文件中描述哪一個組件需要哪一項服務。容器負責將這些聯系在一起。</p>??
  • <p>?</p>??
  • <p>?</p>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • <pre></pre>??
  • ??????
  • ????????<div?style="padding-top:20px">???????????
  • ????????????<p?style="font-size:12px;">版權聲明:本文為博主原創文章,未經博主允許不得轉載。</p>??
  • ????????</div>??
  • 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的解析Spring IOC原理——工厂模式与反射机制的综合应用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。