走進JavaWeb技術世界10:從JavaBean講到Spring

Java 帝國之Java bean (上)

文章轉自: 劉欣 碼農翻身 2016-05-27php

前言: 最近看到到spring 的bean 配置, 忽然想到可能不少人不必定知道這個叫bean的東西的前因後果, 因此就寫個文章來說一下。前端

另外,上次出了開源中國抄襲事件, 爲了防止轉載之後個人公衆號信息被故意刪除, 我在文章的內容中加上了一些 劉欣(微信公衆號:碼農翻身) 這樣的字樣, 可能會形成一些煩擾, 請見諒。 java

我一手創立的Java帝國剛剛成立不久,便受到巨大的打擊, 我派出去佔領桌面開發的部隊幾乎全軍覆沒。 程序員

情報說微軟的Visual Basic 和Borland的Delphi最近在宣傳什麼組件化開發, 難道就是這東西把咱們搞垮了? web

劉欣(微信公衆號:碼農翻身)注:參見《Java :一個帝國的誕生》和《Basic: 一個老兵的自述面試

我趕忙買了一個Visual Basic 過來研究, 果真,這個傢伙確實是方便, 最讓我驚歎的是:它有一個可視化編輯器 ! 算法

我只須要把一個組件(例如按鈕)拖拽到可一個表單上,  設置一下屬性 (顏色,字體), 再添加一個事件(onClick), 最後在onClick中寫點代碼就搞定了 !spring

不只如此,我本身也能夠把個人代碼按規範包裝成一個組件, 發佈出去讓別人使用。sql

我看着手下給我買來的《程序員大本營》光盤, 裏邊居然包含了好幾千個這樣的組件, 有數據庫瀏覽組件, 計時器組件, 顏色選取組件, 甚至還有收發郵件的組件......數據庫

天哪, 這之後開發桌面程序豈不太簡單了 !

怪不得個人Java 被打得滿地找牙!

劉欣(微信公衆號:碼農翻身)注: 90年代末的程序員和學生估計都知道《程序員大本營》, 由csdn的創始人蔣濤製做。

我趕忙打電話給個人干將小碼哥 : 小碼啊, 你趕忙看看這個Visual Basic 和Delphi , 給你7天時間, 咱們Java 也得趕忙搞一套這樣的東西出來。

小嗎絕不含糊, 三天就給我搞了一個東西出來: Java Bean API 規範 。

我翻開一看, 哇塞, 長達114頁 , 因而問他:「這是什麼東西? 我要的可視化編輯器呢Visual Java 呢? 」

劉欣(微信公衆號:碼農翻身)注: 我下載瀏覽了java bean 的規範, 確實是114頁

他說: 「老大, 咱們是個開源的社區, 得充分利用你們的力量, 因此我沒有去作像VB和Delphi那樣的東西, 相反,我定義了一套規範, 只要你們按照這個規範作, 誰均可以用java 作出像VB那樣的可視化開發工具出來。」

「那你說說這個java bean 究竟是什麼規範?」我問。

「首先,一個java bean 其實就是一個普通的java 類, 但咱們對這個類有些要求: 

1. 這個類須要是public 的, 而後須要有個無參數的構造函數

2. 這個類的屬性應該是private 的, 經過setXXX()和getXXX()來訪問

3. 這個類須要能支持「事件」, 例如addXXXXListener(XXXEvent e),  事件能夠是Click事件,Keyboard事件等等, 固然我們也支持自定義的事件。 

4. 咱們得提供一個所謂的自省/反射機制, 這樣能在運行時查看java bean 的各類信息「

5. 這個類應該是能夠序列化的, 便可以把bean的狀態保存的硬盤上, 以便之後來恢復。 

「這些要求看起來也沒啥啊,對程序員來講,不就是個普通的java 類嗎? 到底該怎麼用? 」 

「咱們幻想一下,假設咱們的Java bean 大行其道了, 有個用戶在用一個Visual Java Builder  這樣的可視化開發工具, 當他用這個工具建立應用的時候, 能夠選擇一個叫JButton的組件, 加到一個表單上, 此時Visual Java Builder 就須要把這JButton的類經過反射給new 出來, 因此就須要一個無參數的構造函數了。」

「若是用戶想去設置一下這個JButton的屬性,Visual Java Builder 就須要先用自省/反射來獲取這個JButton有哪些屬性(經過getter/setter), 拿到之後就能夠給用戶顯示一個屬性清單了, 例如背景色, 字體 等等。用戶看到後就能夠設置背景色和字體了,  此時Visual Java Builder 在內部就須要調用這個Bean的setBackgroundCorlor()/setFont() 等方法, 這就是所謂的setXXXX()方法。」

「若是用戶想對這個JButton編程, Visual Java Builder 仍是經過自省/反射來獲取這個JButton有哪些事件, 給用戶展現一個事件清單,例如click , keyboardPressed 用戶能夠選取一個, 而後就能夠寫程序對這個事件編程了。」

「但是那個序列化有什麼用呢?」

「這是由於用戶設計完了之後,可能關掉Visual Java Builder 啊 , 若是不經過序列化把設計好的JButton保存起來, 下次再打開Visual Java Builder , 可就什麼都沒有了」

我想了想, 小碼哥設計的不錯,僅僅用了一個簡單的規範就知足了可視化編輯器的全部要求。 

"那咱們就發佈這個規範吧, 我們本身先作一個可視化編輯器,給別人作個榜樣, 名稱我都想好了, 叫NetBean吧。"

劉欣(微信公衆號:碼農翻身)注:這是我杜撰的, 實際上NetBean這個名稱可能和java bean 並無實際關聯。 

果真不出咱們所料, Java bean 發佈之後, 有力的帶動了Java 的IDE市場,  開發Delphi的Borland公司 也來插了一腳,搞出了一個JBuilder, 風靡一時。 

IBM 搞了一個Visual Age for Java ,  後來搖身一變, 成了一個叫Eclipse的開放平臺,超級受你們歡迎, 它反過頭來把咱們的Netbean 和 JBuilder 逼的快沒有活路了。 

雖然咱們玩的很歡,可是程序員根本不買帳, Java 在桌面開發市場仍是沒有轉機,使用Java bean 建立桌面程序的程序員少之又少, 只有部分像金融、ERP這樣的領地還在堅持。   

看來是無藥可救了。 

可是Java bean 何去何從 ? 丟棄掉太惋惜了,   我和小碼哥商量了一下, 咱們以爲:既然咱們Java在統治了服務器端的編程, 仍是在那裏想一想辦法吧......

上一篇提到Java bean 的規範雖然定義的不錯, 但卻沒有得到意料中的成功, 尤爲是Java帝國所期待的桌面開發組件化市場上。 

我和小碼哥多麼期待CSDN也能出一期《程序員大本營》, 裏邊包含成千上萬的java bean 組件啊。

不要幻想了, 趕忙把java bean 應用在服務器端纔是正事。

JSP + Java Bean

小碼哥建議先用在jsp上試試,  能夠用java bean 來封裝業務邏輯,保存數據到數據庫, 像這樣:

(微信公衆號"碼農翻身"注: 這其實叫作JSP Model 1 )

其中jsp 直接用來接受用戶的請求, 而後經過java bean 來處理業務, 具體的使用方法是:

這就能把HTTP request中的全部參數都設置到 user 這個java bean 對應的屬性上去。 

若是想偷懶, 還能夠這樣:

固然要保證 http request中的參數名和 java bean 中的屬性名是同樣的。 

這個叫作JSP Model 1 的模型受到了不少Java程序員的歡迎 ,  由於他們的應用規模都很小, 用Model 1 使得開發很快速。

實際上, 這種方式和微軟帝國的asp , 以及和開源的php 幾乎同樣。 

但很快就有人來找我抱怨了, 說他們的項目中使用了Model 1 致使整個系統的崩潰。 

他說: 「你知道嗎? 咱們的系統中有好幾千個jsp, 這些jsp互相調用(經過GET/POST), 到了最後調用關係無人能搞懂。 」

其實咱們已經預料到了, 小碼哥對此有個形象的比喻:意大利麪條

這幾千個JSP 就像這碗麪條同樣,攪在一塊兒, 根本理不清楚。

爲了解決這個問題,小碼哥又推出了 :JSP Model 2 ,    這是個模型真正的體現了Model-View-Controller的思想:

Servlet 充當Controller ,  jsp 充當 View 

Java bean 固然就是Model 了!

業務邏輯, 頁面顯示, 和處理過程作了很好的分離。 

基於這個模型的擴展和改進,  不少Web開發框架開始如雨後春筍同樣出現, 其中最著名的就是Struts, SpringMVC 了。

Java Web開發迅速的繁榮了。 

咱們再一次體會到了開放的好處 !

Enterprise Java bean

可是好景不長, 自從Java帝國統治了所謂的「企業級應用」開發領地, 各類各樣的遊行和抗議層出不窮:

「咱們要分佈式」

「咱們要安全」

「咱們要事務」
「咱們要高可用性」

「......」

帝國分析了一下, 其實這些程序員的訴求能夠歸結爲:

「咱們只想關注咱們的業務邏輯, 咱們不想, 也不該該由咱們來處理‘低級’的事務, 多線程,鏈接池,以及其餘各類各類的‘低級’API, 此外Java帝國必定得提供集羣功能, 這樣咱們的一臺機器死機之後,整個系統還能運轉。 」

咱們不能坐着無論, 企業級應用是咱們的命根子。

小碼哥徹夜工做, 最終拿出了一個叫作J2EE的東西, 像Java bean 同樣, 這仍是一個規範, 可是比Java bean 複雜的多, 其中有:

JDBC:  Java 數據庫鏈接, 沒有數據庫的支持怎麼能叫企業級應用?

JNDI :  Java 命名和目錄接口, 經過一個名稱就能夠定位到一個數據源, 連jdbc鏈接都不用了

RMI:  遠程過程調用,  讓一個機器上的java 對象能夠調用另一個機器上的java 對象 , 大家不是要分佈式嗎?

JMS :   Java 消息服務,  可使用消息隊列了, 這不是企業級應用很是須要的嗎?

JTA:  Java 事務管理, 支持分佈式事務, 能在訪問、更新多個數據庫的時候,仍然保證事務, 仍是分佈式。

Java mail : 收發郵件也是必不可少的啊。

劉欣(微信公衆號號:碼農翻身)注:  J2EE 後來改爲了Java EE。

固然還有最最最重要的升級, 小碼哥把java bean 變成了 Enterprise Java bean , 簡稱 EJB

小碼哥宣稱: 

使用了EJB, 你就能夠把精力只放在業務上了, 那些煩人的事務管理, 安全管理,線程 通通交給容器(應用服務器)來處理吧。 

咱們還提供了額外的福利, 只要你的應用服務器是由多個機器組成的集羣, EJB就能夠無縫的運行在這個集羣上, 你徹底不用考慮一個機器死掉了應用該怎麼辦。咱們都幫你搞定了。 

使用Session Bean , 能夠輕鬆的處理你的業務。

使用實體Bean (Entity bean ) , 你和數據庫打交道會變得極爲輕鬆, 甚至sql 都不用寫了。

使用消息驅動Bean(Message Driven bean ) , 你能夠輕鬆的和一個消息隊列鏈接, 處理消息。

聽起來很美好是否是? 

企業級開發領地的程序員們歡呼雀躍, 坐上了J2EE這條船,彷佛一會兒高貴起來, 開始鄙視微軟的ASP, 開源的PHP, Python 等「不入流」的語言了 。

Weblogic , Websphere等符合J2EE規範的應用服務器趁勢而上, 搖旗吶喊, 彷彿一個新的時代要來臨了, 固然他們在背後一直悶聲發大財。 

Sring

有句古話是對的, 捧的越高, 跌的越慘。 

很快,大部分的程序員就發現, 美好的前景並無實現, EJB中用起來極爲繁瑣和笨重, 性能也很差, 爲了得到所謂的分佈式,反而背上了沉重的枷鎖。 

實體Bean很快沒人用了, 就連簡單的無狀態Session bean 也被你們所詬病, 其中一條罪狀就是「代碼的侵入性」。

也是, 小碼哥定義EJB的時候沒考慮那麼多,程序員在定義一個Session bean的時候,須要寫一大堆和業務徹底沒有關係的類。 

還須要被迫實現一些根本不該該實現的接口及其方法: 

爲了哪怕一點點業務邏輯, 咱們都得寫這麼多無用的代碼 ! 程序員們出離憤怒了!

他們發起了一場叫作POJO (Plain Old Java Object)的運動, 高唱這POJO之歌, 要求咱們整改。 

他們但願這個樣子:

public class HelloworldBean{

    public String hello(){

        return "hello world"

    }

}

與此同時,他們還過度的要求保留事務了, 安全了這些必備的東西。 

程序員確實很差伺候,   可是咱們已經被Weblogic, Websphere這些大佬們「綁架」, 想改動談何容易 !

2002年, 小碼哥看到了Rod Johnson寫的一本書《Expert one on one J2EE development withoutEJB》 , 趕忙跑來找我:

「老大, 壞了壞了, 你快看看這本書吧, 這個叫Rod的傢伙寫的這本書直擊咱們的命門,這廝要搞without EJB」

(微信公衆號"碼農翻身"注: 雖然這本書翻譯的不好,但因爲是spring的開山之做,仍是值得讀一下, 最好中英文對照)

豈止是without EJB,  他還「偷偷的」推出了一個叫什麼Spring的框架, 已經迅速的流行開了。

Spring 框架順應了POJO的潮流, 提供了一個spring 的容器來管理這些POJO, 好玩的是也叫作bean 。

看來咱們的java bean 走了一圈又回到了原點。 

對於一個Bean 來講,若是你依賴別的Bean , 只須要聲明便可, spring 容器負責把依賴的bean 給「注入進去「, 起初你們稱之爲控制反轉(IoC)

後來 Martin flower 給這種方式起來個更好的名字,叫「依賴注入」。

若是一個Bean 須要一些像事務,日誌,安全這樣的通用的服務, 也是隻須要聲明便可, spring 容器在運行時可以動態的「織入」這些服務, 這叫AOP。 

後來我和小碼哥商量, 咱們EJB也學習Spring , 簡化開發和配置, 可是爲時已晚, Spring 已經成爲事實上的標準了!程序員已經被spring 拉走了!

不過令咱們欣慰的是, spring和spring mvc極大的增長了咱們對web開發領地的統治力, java 帝國更增強盛了。 

(全文完)

Spring 的本質系列(1) -- 依賴注入

轉自: 劉欣 碼農翻身 2016-06-25

轉載 碼農翻身微信公衆號 2016-06-25 劉欣 《Spring 的本質系列(1) -- 依賴注入》

1. 對象的建立

       面向對象的編程語言是用類(Class)來對現實世界進行抽象, 在運行時這些類會生成對象(Object)。 
       固然,單獨的一個或幾個對象根本沒辦法完成複雜的業務, 實際的系統是由千千萬萬個對象組成的, 這些對象須要互相協做才能幹活,例如對象A調用對象B的方法,那必然會提出一個問題:對象A怎麼才能得到對象B的引用呢?
       最簡單的辦法無非是: 當對象A須要使用對象B的時候, 把它給new 出來 ,這也是最經常使用的辦法, java 不就是這麼作的?例如:  Apple a = new Apple();
       後來業務變複雜了, 抽象出了一個水果(Fruit)的類, 建立對象會變成這個樣子:
       Fruit f1 = new Apple();
       Fruit f2 = new Banana();
       Fruit f3 = ......
      很天然的,相似下面的代碼就會出現:

       這樣的代碼若是散落在各處,維護起來將會痛苦不堪, 例如你新加一個水果的類型Orange, 那得找到系統中全部的這些建立Fruit的地方,進行修改, 這絕對是一場噩夢。
 解決辦法也很簡單, 前輩們早就總結好了:工廠模式 

       工廠模式,以及其餘模式像抽象工廠, Builder模式提供的都是建立對象的方法。這背後體現的都是「封裝變化」的思想。這些模式只是一些最佳實踐而已: 起了一個名稱、描述一下解決的問題、使用的範圍和場景,碼農們在項目中還得本身去編碼實現他們。

2. 解除依賴

        咱們再來看一個稍微複雜一點, 更加貼近實際項目的例子:
        一個訂單處理類,它會被定時調用:  查詢數據庫中訂單的處理狀況, 必要時給下訂單的用戶發信。

        看起來也沒什麼難度, 須要注意的是不少類一塊兒協做了, 尤爲是OrderProcessor , 它依賴於OrderService 和 EmailService這兩個服務,它獲取依賴的方式就是經過單例方法。
        若是你想對這個process方法進行單元測試--這也是不少優秀的團隊要求的-- 麻煩就來了。 
        首先OrderService 確實會從真正的數據庫中取得Order信息,你須要確保數據庫中有數據, 數據庫鏈接沒問題,實際上若是數據庫鏈接Container(例如Tomcat)管理的, 你沒有Tomcat很難創建數據庫鏈接。
       其次這個EmailService 真的會對外發郵件, 你可不想對真正的用戶發測試郵件,固然你能夠修改數據庫,把郵件地址改爲假的,但那樣很麻煩, 而且EmailService 會拋出一堆錯誤來,很不爽。
       全部的這些障礙, 最終會致使脆弱的單元測試: 速度慢, 不可重複,須要手工干預,不能獨立運行。
       想克服這些障礙, 一個可行的辦法就是不在方法中直接調用OrderService和EmailService的getInstance()方法, 而是把他們經過setter方法傳進來。

       經過這種方式,你的單元測試就能夠構造一個假的OrderService 和假的EmailService 了。
       例如OrderService 的冒牌貨能夠是MockOrderService , 它能夠返回你想要的任何Order 對象, 而不是從數據庫取。MockEmailService 也不會真的發郵件, 而是把代碼中試圖發的郵件保存下來, 測試程序能夠檢查是否正確。
       你的測試代碼多是這樣的:

        固然, 有經驗的你立刻就會意識到: 須要把OrderService 和 EmailService 變成 接口或者抽象類, 這樣才能夠把Mock對象傳進來。 
        這其實也遵循了面向對象編程的另一個要求: 對接口編程, 而不是對實現編程。

3. Spring 依賴注入

        囉囉嗦嗦說了這麼多, 快要和Spring扯上關係了。
       上面的代碼其實就是實現了一個依賴的注入,把兩個冒牌貨注入到業務類中(經過set方法), 這個注入的過程是在一個測試類中經過代碼完成的。
       既然能把冒牌貨注入進去,  那毫無疑問,確定也能把一個正經的類安插進去, 由於setter 方法接受的是接口,而不是具體類。

       用這種方式來處理對象之間的依賴, 會強迫你對接口編程, 好處顯而易見。 
       隨着系統複雜度的增加, 這樣的代碼會愈來愈多, 最後也會變得難於維護。 
       能不能把各個類之間的依賴關係統一維護呢?
       能不能把系統作的更加靈活一點,用聲明的方式而不是用代碼的方式來描述依賴關係呢?
       確定能夠, 在Java 世界裏,若是想描述各類邏輯關係, XML是不二之選:

        這個xml 挺容易理解的, 可是僅僅有它還不夠, 還缺一個解析器(假設叫作XmlAppContext)來解析,處理這個文件,基本過程是:
         0. 解析xml, 獲取各類元素
         1. 經過Java反射把各個bean 的實例建立起來: com.coderising.OrderProcessor   , OrderServiceImpl, EmailServiceImpl. 
         2. 仍是經過Java反射調用OrderProcessor的兩個方法:setOrderService(....)  和 setEmailService(...) 把orderService , emailService 實例 注入進去。
        應用程序使用起來就簡單了:
        XmlAppContext ctx = new XmlAppContext("c:\bean.xml");
        OrderProcessor op = (OrderProcessor) ctx.getBean("order-processor");
        op.process();
        其實Spring的處理方式和上面說的很是相似, 固然Spring 處理了更多的細節,例如不只僅是setter方法注入, 還能夠構造函數注入,init 方法, destroy方法等等, 基本思想是一致的。

       既然對象的建立過程和裝配過程都是Spring作的, 那Spring 在這個過程當中就能夠玩不少把戲了, 好比對你的業務類作點字節碼級別的加強, 搞點AOP什麼的, 這都不在話下了。 

4. IoC vs DI

        「不要給咱們打電話,咱們會打給你的(don‘t call us, we‘ll call you)」這是著名的好萊塢原則。
        在好萊塢,把簡歷遞交給演藝公司後就只有回家等待。由演藝公司對整個娛樂項目徹底控制,演員只能被動式的接受公司的差使,在須要的環節中,完成本身的演出。
        這和軟件開發有必定的類似性, 演員們就像一個個Java Object, 最先的時候本身去建立本身所依賴的對象,   有了演藝公司(Spring容器)的介入,全部的依賴關係都是演藝公司搞定的, 因而控制就翻轉了 
        Inversion of Control, 簡稱IoC。 可是IoC這個詞不能讓人更加直觀和清晰的理解背後所表明的含義, 因而Martin Flower先生就創造了一個新詞 : 依賴注入 (Dependency Injection,簡稱DI),  是否是更加貼切一點?

Spring本質系列(2)-AOP

原創: 劉欣 碼農翻身 2016-06-30

   聽說有些詞彙很是熱門和神奇, 若是你常常把它掛在嘴邊,就能讓本身功力大漲, 能夠輕鬆找到理想的高薪的工做,這些詞就包括上一篇文章(《Spring本質系列(1) --依賴注入》)中聊過的IoC 和 DI, 也包括今天要聊的AOP。
       AOP(Aspect Oriented Programming)就是面向切面的編程, 爲何是面向切面, 而不是面向對象呢?

1. 問題來源

      咱們在作系統設計的時候,一個很是重要的工做就是把一個大系統作分解, 按業務功能分解成一個個低耦合、高內聚的模塊,就像這樣:

       可是分解之後就會發現有些頗有趣的東西, 這些東西是通用的,或者是跨越多個模塊的:
       日誌: 對特定的操做輸出日誌來記錄
       安全:在執行操做以前進行操做檢查
       性能:要統計每一個方法的執行時間
       事務:方法開始以前要開始事務, 結束後要提交或者回滾事務
       等等....
       這些能夠稱爲是非功能需求, 但他們是多個業務模塊都須要的, 是跨越模塊的, 把他們放到什麼地方呢?
       最簡單的辦法就是把這些通用模塊的接口寫好, 讓程序員在實現業務模塊的時候去調用就能夠了,碼農嘛,辛苦一下也沒什麼。

      這樣作看起來沒問題, 只是會產生相似這樣的代碼:

      這樣的代碼也實現了功能,可是看起來很是的不爽, 那就是日誌,性能,事務 相關的代碼幾乎要把真正的業務代碼給淹沒了。
      不只僅這一個類須要這麼幹, 其餘類都得這麼幹, 重複代碼會很是的多。
      有經驗的程序員還好, 新手忘記寫這樣的非業務代碼簡直是必然的。

2. 設計模式:模板方法

      用設計模式在某些狀況下能夠部分解決上面的問題,例如著名的模板方法:

       在父類(BaseCommand)中已經把那些「亂七八糟「的非功能代碼都寫好了, 只是留了一個口子(抽象方法doBusiness())讓子類去實現。
       子類變的清爽, 只須要關注業務邏輯就能夠了。
       調用也很簡單,例如:
       BaseCommand  cmd = ...  得到PlaceOrderCommand的實例...
       cmd.execute();
       可是這樣方式的巨大缺陷就是父類會定義一切: 要執行哪些非功能代碼, 以什麼順序執行等等
      子類只能無條件接受,徹底沒有反抗餘地。
       若是有個子類, 根本不須要事務, 可是它也沒有辦法把事務代碼去掉。

3. 設計模式:裝飾者

      若是利用裝飾者模式, 針對上面的問題,能夠帶來更大的靈活性:

       如今讓這個PlaceOrderCommand 可以打印日誌,進行性能統計
       Command cmd = new LoggerDecorator(
              new PerformanceDecorator(
                  new PlaceOrderCommand()));
       cmd.execute();

       若是PaymentCommand 只須要打印日誌,裝飾一次就能夠了:
       Command cmd = new LoggerDecorator(
              new PaymentCommand());
       cmd.execute();
       可使用任意數量裝飾器,還能夠以任意次序執行(嚴格意義上來講是不行的), 是否是很靈活? 

4. AOP

       若是仔細思考一下就會發現裝飾者模式的不爽之處:
       (1)  一個處理日誌/性能/事務 的類爲何要實現 業務接口(Command)呢?
       (2) 若是別的業務模塊,沒有實現Command接口,可是也想利用日誌/性能/事務等功能,該怎麼辦呢?

       最好把日誌/安全/事務這樣的代碼和業務代碼徹底隔離開來,由於他們的關注點和業務代碼的關注點徹底不一樣 ,他們之間應該是正交的,他們之間的關係應該是這樣的:

       若是把這個業務功能當作一層層面包的話, 這些日誌/安全/事務 像不像一個個「切面」(Aspect) ?
       若是咱們能讓這些「切面「能和業務獨立,  而且可以很是靈活的「織入」到業務方法中, 那就實現了面向切面編程(AOP)!

5. 實現AOP

       如今咱們來實現AOP吧, 首先咱們得有一個所謂的「切面「類(Aspect), 這應該是一個普通的java 類,不用實現什麼「亂七八糟」的接口。以一個事務類爲例:

       咱們想達到的目的只這樣的: 對於com.coderising這個包中全部類的execute方法, 在方法調用以前,須要執行Transaction.beginTx()方法, 在調用以後, 須要執行Transaction.commitTx()方法。
       暫時停下腳步分析一下。
      「對於com.coderising這個包中全部類的execute方法」 , 用一個時髦的詞來描述就是切入點(PointCut) , 它能夠是一個方法或一組方法(能夠經過通配符來支持,你懂的)
      」在方法調用以前/以後 , 須要執行xxx「 , 用另一個時髦的詞來描述就是通知(Advice)
       碼農翻身認爲,PointCut,Advice 這些詞實在是不直觀, 其實Spring的做者們也是這麼想的 :  These terms are not Spring-specific… unfortunately, AOP terminology is not particularly intuitive; however, it would be even more confusing if Spring used its own terminology.
       固然,想描述這些規則, xml依然是不二之選:

       注意:如今Transaction這個類和業務類在源代碼層次上沒有一點關係,徹底隔離了。隔離是一件好事情, 可是立刻給咱們帶來了大麻煩 。
       Java 是一門靜態的強類型語言, 代碼一旦寫好, 編譯成java class 之後 ,能夠在運行時經過反射(Reflection)來查看類的信息, 可是想對類進行修改很是困難。 
       而AOP要求的偏偏就是在不改變業務類的源代碼(其實大部分狀況下你也拿不到)的狀況下, 修改業務類的方法, 進行功能的加強,就像上面給全部的業務類增長事務支持。
      爲了突破這個限制,你們能夠說是費盡心機, 如今基本是有這麼幾種技術:
      (1) 在編譯的時候, 根據AOP的配置信息,悄悄的把日誌,安全,事務等「切面」代碼 和業務類編譯到一塊兒去。
      (2) 在運行期,業務類加載之後, 經過Java動態代理技術爲業務類生產一個代理類, 把「切面」代碼放到代理類中,  Java 動態代理要求業務類須要實現接口才行。
      (3) 在運行期, 業務類加載之後, 動態的使用字節碼構建一個業務類的子類,將「切面」邏輯加入到子類當中去, CGLIB就是這麼作的。
      Spring採用的就是(1) +(2) 的方式,限於篇幅,這裏再也不展開各類技術了, 無論使用哪種方式, 在運行時,真正幹活的「業務類」其實已經不是原來單純的業務類了, 它們被AOP了 !、

微信公衆號【黃小斜】大廠程序員,互聯網行業新知,終身學習踐行者。關注後回覆「Java」、「Python」、「C++」、「大數據」、「機器學習」、「算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「筆試」、「面試」、「面經」、「計算機基礎」、「LeetCode」 等關鍵字能夠獲取對應的免費學習資料。

                     

相關文章
相關標籤/搜索