1. 程式人生 > >面向物件含義+Spring管理本質(通俗的案例顛覆你的認知)

面向物件含義+Spring管理本質(通俗的案例顛覆你的認知)

       我們在學習java的時候,都是在一個main方法中進行各種各樣的程式碼活動。後來學到了面向物件,知道了很多流程是通過不同的物件合作來完成業務邏輯。我們在main方法中,new了很多個物件,完成了業務功能,然後這個main方法就結束了,虛擬機器停止了.

一個main方法,他是一個執行緒,所有的邏輯程式碼順序的再執行緒上執行,我們遇到了一個問題,需要一個物件了,ok,我們new了一個物件,然後完成了業務邏輯. 執行緒結束,物件被回收. 實際上,main方法也是一個方法,所以這些線上程中建立的物件,在main方法作用域的範圍之外都會被銷燬了。

       希望大家想象這樣一個過程:假如你開了一間房產公司,你是老闆,你沒有員工,這個時候,有一個客戶上門辦業務,你就零時的僱傭了一個員工,把你的業務辦完了,然後解僱了這個員工.又有一個客戶來了,你又去僱傭了一個員工,結束了業務你又解僱了他.並且還有一個問題,那就是來了這個客戶,他還要等著你,去把員工找好了,他的業務才可以得到辦理,整個過程,分成了招員工+辦業務兩件事. 你的客戶一定會抱怨:怎麼不提前把員工請好呢?這樣多耽誤我的時間啊!

       回到剛才的執行緒的問題:執行緒是用來幹什麼? 

      執行緒就是用來辦業務的,我們的執行緒資源提供了程式的計算能力,處理問題的能力. 可是,你在碰到一個問題了:你需要一個人來解決問題的時候,你發現你沒有這個人,於是,你把這個業務計算資源,用來去創造物件了.所有的業務就要等著你把物件建立完畢了,才能繼續進行下去...這樣,一個執行緒並沒有專注的幹自己的業務,而是一邊建立物件,一邊辦理業務.我們可不可以改進一下我們的程式呢?

       在main方法啟動的時候,提前建立好我們的業務需要的所有的物件,放在一個池子裡呢?我們需要誰的時候,直接叫一聲,池子裡的物件就跑出來了。直接來辦理業務不就好了嗎?
       我想到了一個方法,那就是在main方法頭部建立了一個map,把然後new很多個物件,給物件起一個名字:比如經紀人A、經紀人B、銀行代表C 放在map中。後面的業務處理部分,直接map來get誰,辦理業務 但是,這樣價效比不高.因為我們在學習java的時候,都是單執行緒程式,程式都是一次性的。這種java程式不能稱之為一個持續提供服務的系統,我們開一個房地產經紀公司,也不是一錘子買賣。我們需要僱傭很多員工,在很長時間內,重複服務很多很多的客戶.這個過程是持續的,不間斷的,我們不能說,等到公司開起來了,來了客戶,我們才知道去找人.而是,在公司建立起來,還沒有對外提供服務的時候,所有的員工都準備好了包括 會計,銷售,技術,客戶代表所有這些人都各就各位了並且,這些系統中的物件要能夠服務不同的客戶,不同的執行緒,那麼他們應該在全域性系統範圍是可見的,不受任何一個執行緒,或者方法的結束而結束。

      我們想到了static類,是嗎?因為static池,可以在全域性範圍內來儲存這些物件

比如,我們不用spring來建立一個web程式,我們可能會有一個監聽器,web容器啟動了.監聽器中給一個靜態池(一個靜態類)中的map屬性中新增所有web系統需要服務的物件,各類dao,各類service等 把所有這些物件,都建立好,各就各位。

假如你的系統需要1000個物件,那麼,你就需要在這個池類中部署1000個,然後你在servlet中辦理業務的時候,你需要一個人了,直接獲取這個池類,得到這個物件.而不是new一個,因為new一個就是一錘子買賣了.方法結束,物件被回收.這個做法就是,applicationContext.getBean的基本雛形了。

     一個靜態類,可以提供全域性儲存的功能 但是,他並不專業.一個static類,他並不是專業的池,spring提供了很多特性。比如,可以設定是否是全域性範圍,singleTon,還是一次建立就銷燬,還是session範圍有效.spring的池,很多選項.但是一個static類來提供全域性池,是很簡陋的,不專業的.我只是單純的比靜態類和IOC容器在物件管理這塊的問題。

假如,我們用了靜態類來管理物件,可能我們有一個BeanContext這樣一個靜態類,然後在監聽器中,把所有的系統需要的全域性物件,都set到這個類中的某個map上再servlet中需要這些物件的時候,直接靜態類,BeanContext.getBean來獲取靜態方法,這是一個很大的進步,至少,我也提供了系統物件的管理了。但是,有一個問題,我的static類提供了物件管理,我可以隨意的獲取一個service物件,我也可以隨意的獲取一個dao物件,這都沒有問題,但是,你在servlet中辦理業務的時候你肯定有三個步驟:獲取servcice,獲取dao,然後把獲取來的dao設定到獲取來的servic額上面.你需要在業務程式碼中做這樣的一個事情。這樣,你的業務程式碼還是單純的業務程式碼嗎?
     你又陷入到這種困境中了:你開了一家公司,明明老張和老王是上下級關係,可是每一次,來人辦業務,你都要重複的建立這種關係----------Spring的自動裝配。

雖然,你沒有重複建立物件了,但是你在重複建立這種關係。你肯定會說在監聽器中就建立好關係呀,監聽器程式碼中把全部的物件管理好之後,然後set所有的關係。但是這個假如你的公司很大有10000個物件各種關係錯綜複雜,你會set到死,你也很難用程式碼實現。如果你真的企圖去實現這樣的程式碼,你其實,就很明白你在幹一件什麼事情了那就是重複造輪子,造spring的輪子了

     spring是怎麼做的?在一個類中用autowired註解,spring的ioc先把所有的物件管理起來,然後發現這些類中的autowired註解自動的給你執行裝配,這就是web程式中,spring的監聽器,乾的事情啟動監聽器,獲取配置檔案,根據配置檔案掃描指定的classpath下的類,例項化他,根據類中的註解資訊,來執行裝配,裝配結束,監聽方法完成,把IOC容器掛靠再ServletContext上面,這樣,我們的業務程式碼中,再也看不到new物件了,因為提前構建起來了,再也看不到set屬性了,因為自動裝配了。

       java是面向物件的,而物件如何被管理?我們天天都在提,面向物件面向物件可是從來沒有考慮過,一個java系統,他們的物件的管理,配置,協調方式 所謂的控制反轉就是你不再需要主動去set屬性,交給我就行了,我來幫你,這個控制權利,我來幫你做你根本不需要知道物件在哪裡,你也不需要管他是什麼型別,全部由我給你準備好。

        有一個概念叫做EJB,EJB是官方的javaEE應用容器框架,它和spring類似,提供物件的管理,依賴反轉,但是他有一個問題:就是EJB有很強烈的限制,比如企業Bean,實體Bean,都要符合EJB規範的物件。他才可以進行部署和管理。而spring不同,spring是基於普通pojo的,任何物件,來者不拒。EJB提供了整個javaEE企業開發的通用框架,結構,所有的一切,都要按照他的標準來部署,來配置,來管理,比如一個公司框架,財務,銷售,技術支援,售後 都給你規定死了,你必須要按照這個規範,來部署整個系統所需要的元件,物件。而spring,隨意,你隨便部署一個HelloWorld物件吧,沒有人會管你。

     一個系統,由成千上萬個物件,元件構成,而這一切,都是部署在系統物件管理平臺上的 spring是一個輕量級的javaEE平臺
他非常開放,非常好用,可以簡單到只有一個HelloWorld物件,也可以是一個超大型的企業系統如果沒有spring,沒有EJB,你可能需要自己開發系統的物件和元件管理和配置平臺,如果系統很大,你很難 幾乎不可能,你肯定會用javaEE的這樣的框架來幫你,無論是spring還是ejb

實際上,是一個平臺,javaEE的構建平臺,他就像是一個主機板,我們在這個主機板上面部署不同的元件,不同的元件之間還有關聯關係.你見過主機板嗎?上面密密麻麻的部署了很多很多元件,這個主機板就是spring平臺. 企業級應用,就是基於這塊板子來部署的.我們可以把EJB看作是規範,顯示卡介面,cpu介面 EJB很強的限制 你必須按照主機板規範來部署.但是spring就是一個光板,你們現在知道,為什麼總有人說,和spring整合這種說法了吧.其實不是和spring整合,而是我們需要再spring中來給他整合,整合到大家庭中.

      有人說:EJB像一種規範,Spring像一個平臺。 其實不能這麼說,EJB提供了標準組件、全套解決方案,你拿到EJB主機板的時候,很多東西都已經內建了。而spring是光板所以稱之為輕量級javaEE平臺,輕量級也就意味著一些東西還得你自己來。持久化嘛,我需要一個sqlSessionFactory,部署進去安上去,等等,連線池,安進去。什麼?還需要和redis服務,redis客戶端部署進去,還需要和activemq整合,那麼,把mq元件部署上面。這有些顛覆你們對java的認識,你們眼中的java程式應該是你們學習java,main方法那些程式邏輯,實際上,一個元件,一個服務,甚至是一個子系統 他們都是物件剛才已經提到了,為什麼需要物件管理和配置了 你們如果只是寫個main方法,跑一跑,結束 。這不叫企業級應用程式,好了,我剛才提到了spring管理平臺,但是,我們的程式中,如何來使用spring管理的物件呢。它的本質還是管理物件,我們最終要拿到物件才是啊!我們在哪裡拿到的物件啊? 好像我們從來沒有想過這個問題,只知道@conponment 只知道@autowired 已經麻木了!

      以springmvc為例子 springmvc中的Controller裡面被裝配了service,service內部裝配了dao。但是這個Controller是在哪裡被獲取,被取出來的?你好像沒有在哪裡個地方getBean獲取這個Controller吧。就是說,無論spring怎麼裝配,怎麼管理,我們最終都要找他拿最外層的那個入口物件她如果只是存起來,裝配好,有什麼用 必須要提供出來呀!所以,這就是springmvc的對映器mapping乾的事情了 它可以找到Controller,找到了Controller,意味著找到了整個入口你們開發的Controller被添加了@Controller註解,被管理,被裝配 最終被對映器發現。

     多提一嘴 是不是整個應用程式的所有的物件都應該被容器管理呢?顯然不是,舉例子:你開了一家房地產公司、經紀公司,你的員工,裝置,電腦,合作合辦都是提前部署好了,但是,不代表,你在經營的活動中就不會出現新生的臨時性事物 比如,你的客戶就是臨時性的,來了一個客戶,業務辦理結束,客戶物件就沒了。你的經營活動中出現了新東西,臨時性的,比如一筆業務過程中的一個訂單,一筆交易,他們都是實效性很強的。這些東西叫做實體,而spring管理的,一般都是元件、系統元件說到這個問題,可能就會出現那些什麼實體,vo,dto,服務物件,dao,等等 這些都是整個系統中出現的物件,但是她們有不同的角色,不同的定義嗯,基本上差不多了

spring就是java企業級目前事實上的標準,spring是所有框架中,最核心的,最重要的一個。但是它的存在感比較低,對很多人來說就是註解,就是寫配置檔案。很少有人真的去理解它!!!





                                                                                                                                                       -----謎之家大佬