日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

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

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

從一個(gè)例子開(kāi)始講起:

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

?????

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

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

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

  • ?最后我們編寫(xiě)一個(gè)測(cè)試類(lèi)對(duì)這兩個(gè)類(lèi)的sayHelloWorld(String name)方法進(jìn)行測(cè)試,下面是該類(lèi)的內(nèi)容:

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

    現(xiàn)實(shí)生活中我們總是把同一類(lèi)產(chǎn)品放在一個(gè)工廠中生產(chǎn),消費(fèi)者只需要告訴工廠自己需要這一類(lèi)產(chǎn)品中的哪一種產(chǎn)品,工廠就能夠生產(chǎn)出對(duì)應(yīng)的產(chǎn)品,從而完成交易。

    這里我們把上面例子中的HelloWorldTest類(lèi)想象為消費(fèi)者,而Chinese和American類(lèi)想象為產(chǎn)品,根據(jù)上面的例子,我們可以看到每當(dāng)HelloWorldTest這個(gè)消費(fèi)者需要一個(gè)產(chǎn)品時(shí)都要去自己去生產(chǎn)(new),這樣消費(fèi)者就不得不去了解各個(gè)產(chǎn)品的內(nèi)部結(jié)構(gòu)及生產(chǎn)過(guò)程。顯然對(duì)于消費(fèi)者來(lái)說(shuō)這樣是很麻煩的。

    而在程序設(shè)計(jì)領(lǐng)域中這個(gè)問(wèn)題就叫做強(qiáng)耦合問(wèn)題,HelloWorldTest類(lèi)與ChineseAmerican這兩個(gè)類(lèi)都存在強(qiáng)耦合關(guān)系。設(shè)想一下,如果程序中的很多類(lèi)都需要用到ChineseAmerican類(lèi)這兩個(gè)類(lèi),那么每個(gè)類(lèi)就必須和這兩個(gè)類(lèi)強(qiáng)耦合,而且現(xiàn)實(shí)的項(xiàng)目中類(lèi)似于Chinese這種類(lèi)往往不僅兩個(gè),這樣會(huì)使得整個(gè)程序的耦合度很高,增大程序的復(fù)雜度。這時(shí)我們就想到,能否也使用一個(gè)工廠來(lái)生產(chǎn)這些類(lèi),這樣如果某個(gè)類(lèi)需要用到工廠中的哪個(gè)類(lèi),就只要通過(guò)和工廠生產(chǎn)就行了,從而降低了整個(gè)程序的耦合度。

    下面看看工廠模式是如何實(shí)現(xiàn)的:

    首先建立接口類(lèi)Human.java,其內(nèi)容如下:

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

    并將American.java類(lèi)和Chinese.java類(lèi)改為實(shí)現(xiàn)該接口,即類(lèi)頭分別改成:public class American implements Humanpublic class Chinese implements Human。

    接著編寫(xiě)HumanFactory.java工廠類(lèi),其內(nèi)容為

    ?

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

    最后我們還需要修改測(cè)試類(lèi)HelloWorld.java類(lèi),修改后的內(nèi)容如下:?

    ?

    [java]?view plaincopyprint?
  • public?class?HelloWorldTest?{??
  • ??
  • ???????/**?*//**?
  • ????????*?測(cè)試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");??
  • ??????????????}??
  • }??

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

    ?

    ?(二)Spring IOC的原理

    首先我們來(lái)講下為什么要引入IOC:

    假設(shè)上面舉例的那個(gè)程序已經(jīng)部署到服務(wù)器中,并已經(jīng)上線運(yùn)行,這時(shí)項(xiàng)目來(lái)了這樣一個(gè)新需求:增加一個(gè)Japanese類(lèi),并且在HelloWorldTest 類(lèi)中調(diào)用Japanese的sayHelloWorld方法。在沒(méi)有引入IOC之前,很顯然我們?yōu)榱诉@個(gè)新需求,必須把項(xiàng)目停止下來(lái),然后從新編譯HumanFactory 和HelloWorldTest這兩個(gè)類(lèi),最后再重新上線運(yùn)行。

    而使用IOC,則能夠在不重新編譯部署的情況下實(shí)現(xiàn)上面的新需求!

    那么我們來(lái)看一下IOC是去怎么實(shí)現(xiàn)這個(gè)新需求的:?

    ?首先我們?cè)赾om.human包內(nèi)創(chuàng)建一個(gè)Japanese類(lèi):

    [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;??
  • ?????}??
  • }??

  • ?

    然后對(duì)HelloWorldTest 類(lèi)做如下修改

    ?

    [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("極度暴走");??
  • ?????????????}??
  • }??
  • ?

    然后我們?cè)赽eans.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?便會(huì)去調(diào)用Japanese類(lèi)的sayHelloWorld()方法;用這種形式,我們只要修改beans.xml的配置便可以改變HelloWorldTest?類(lèi)中human對(duì)象,并且不需要重新部署項(xiàng)目,這樣就實(shí)現(xiàn)了human對(duì)象的熱拔插。</p>??
  • <p>從上面的代碼可以看到spring?IOC的這種實(shí)現(xiàn)方式主要是靠BeanFactory這個(gè)類(lèi),那么這個(gè)BeanFactory到底有什么神奇之處呢?</p>??
  • <p>下面讓我們模擬實(shí)現(xiàn)一個(gè)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工廠類(lèi).??????
  • ?*/??
  • 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反射機(jī)制,通過(guò)class的名稱(chēng)獲取Class對(duì)象??
  • ????????????????????????????Class?bean?=?Class.forName(cls.getText());??
  • ????????????????????????????//獲取對(duì)應(yīng)class的信息??
  • ????????????????????????????java.beans.BeanInfo?info?=?java.beans.Introspector.getBeanInfo(bean);??
  • ????????????????????????????//獲取其屬性描述??
  • ????????????????????????????java.beans.PropertyDescriptor?pd[]?=?info.getPropertyDescriptors();??
  • ????????????????????????????//設(shè)置值的方法??
  • ????????????????????????????Method?mSet?=?null;??
  • ????????????????????????????//創(chuàng)建一個(gè)對(duì)象??
  • ????????????????????????????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的反射機(jī)制調(diào)用對(duì)象的某個(gè)set方法,并將值設(shè)進(jìn)去??
  • ???????????????????????????????????mSet.invoke(obj,?value);??
  • }??
  • }??
  • }??
  • ??
  • //將對(duì)象放入beanMap中,其中key為id值,value為對(duì)象??
  • beanMap.put(id.getText(),?obj);??
  • }??
  • }?catch?(Exception?e)?{??
  • ????System.out.println(e.toString());??
  • }??
  • }??
  • ??
  • ???????/**?*//**??
  • ????????*?通過(guò)bean的id獲取bean的對(duì)象.??
  • ????????*?@param?beanName?bean的id??
  • ????????*?@return?返回對(duì)應(yīng)對(duì)象??
  • ????????*/??
  • ???????public?Object?getBean(String?beanName)?{??
  • ??????????????Object?obj?=?beanMap.get(beanName);??
  • ??????????????return?obj;??
  • ???????}??
  • ??
  • ???????/**?*//**??
  • ????????*?測(cè)試方法.??
  • ????????*?@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>測(cè)試方法的執(zhí)行結(jié)果:你好,極度暴走</p>??
  • <p>漩渦鳴人</p>??
  • <p>22</p>??
  • <p>?</p>??
  • <p>總結(jié):從上面的代碼可以看出Spring的bean工廠主要實(shí)現(xiàn)了以下幾個(gè)步驟</p>??
  • <p>1.解析配置文件(bean.xml)</p>??
  • <p>2.使用反射機(jī)制動(dòng)態(tài)加載每個(gè)class節(jié)點(diǎn)中配置的類(lèi)</p>??
  • <p>3.為每個(gè)class節(jié)點(diǎn)中配置的類(lèi)實(shí)例化一個(gè)對(duì)象</p>??
  • <p>4.使用反射機(jī)制調(diào)用各個(gè)對(duì)象的seter方法,將配置文件中的屬性值設(shè)置進(jìn)對(duì)應(yīng)的對(duì)象</p>??
  • <p>5.將這些對(duì)象放在一個(gè)存儲(chǔ)空間(beanMap)中</p>??
  • <p>6.使用getBean方法從存儲(chǔ)空間(beanMap)中取出指定的JavaBean</p>??
  • <p>?</p>??
  • <p>PS:IOC的標(biāo)準(zhǔn)定義:</p>??
  • <p>(Inversion?of?Control)?</p>??
  • <p>  中文譯為:?控制反轉(zhuǎn)</p>??
  • <p>  IOC的基本概念是:不創(chuàng)建對(duì)象,但是描述創(chuàng)建它們的方式。在代碼中不直接與對(duì)象和服務(wù)連接,但在配置文件中描述哪一個(gè)組件需要哪一項(xiàng)服務(wù)。容器負(fù)責(zé)將這些聯(lián)系在一起。</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;">版權(quán)聲明:本文為博主原創(chuàng)文章,未經(jīng)博主允許不得轉(zhuǎn)載。</p>??
  • ????????</div>??
  • 《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專(zhuān)家共同創(chuàng)作,文字、視頻、音頻交互閱讀

    總結(jié)

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

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。