走進JavaWeb技術世界10:從JavaBean講到Spring
微信公眾號【黃小斜】大廠程式設計師,網際網路行業新知,終身學習踐行者。關注後回覆「Java」、「Python」、「C++」、「大資料」、「機器學習」、「演算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「筆試」、「面試」、「面經」、「計算機基礎」、「LeetCode」 等關鍵字可以獲取對應的免費學習資料。
微信公眾號【黃小斜】大廠程式設計師,網際網路行業新知,終身學習踐行者。關注後回覆「Java」、「Python」、「C++」、「大資料」、「機器學習」、「演算法」、「AI」、「Android」、「前端」、「iOS」、「考研」、「BAT」、「校招」、「筆試」、「面試」、「面經」、「計算機基礎」、「LeetCode」 等關鍵字可以獲取對應的免費學習資料。
Java 帝國之Java bean (上)
轉自: 劉欣 2016-05-27
前言: 最近看到到spring 的bean 配置, 突然想到可能很多人不一定知道這個叫bean的東西的來龍去脈, 所以就寫個文章來講一下。
另外,上次出了開源中國 , 為了防止轉載以後我的公眾號資訊被故意刪除, 我在文章的內容中加上了一些 劉欣(微信公眾號:碼農翻身) 這樣的字樣, 可能會造成一些煩擾, 請見諒。
我一手創立的Java帝國剛剛成立不久,便受到巨大的打擊, 我派出去佔領桌面開發的部隊幾乎全軍覆沒。
情報說微軟的Visual Basic 和Borland的Delphi最近在宣傳什麼元件化開發, 難道就是這東西把我們搞垮了?
劉欣(微信公眾號:碼農翻身)注:參見《 》和《 》
我趕緊買了一個Visual Basic 過來研究, 果然,這個傢伙確實是方便, 最讓我驚歎的是:它有一個視覺化編輯器 !
我只需要把一個元件(例如按鈕)拖拽到可一個表單上, 設定一下屬性 (顏色,字型), 再新增一個事件(onClick), 最後在onClick中寫點程式碼就搞定了 !
不僅如此,我自己也可以把我的程式碼按規範包裝成一個元件, 釋出出去讓別人使用。
我看著手下給我買來的《程式設計師大本營》光碟, 裡邊竟然包含了好幾千個這樣的元件, 有資料庫瀏覽元件, 計時器元件, 顏色選取元件, 甚至還有收發郵件的元件......
天哪, 這以後開發桌面程式豈不太簡單了 !
怪不得我的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 工程師的技術小站。作者黃小斜,專注 Java 相關技術:SSM、SpringBoot、MySQL、分散式、中介軟體、叢集、Linux、網路、多執行緒,偶爾講點Docker、ELK,同時也分享技術乾貨和學習經驗,致力於Java全棧開發!(關注公眾號後回覆”Java“即可領取 Java基礎、進階、專案和架構師等免費學習資料,更有資料庫、分散式、微服務等熱門技術學習影片,內容豐富,兼顧原理和實踐,另外也將贈送作者原創的Java學習指南、Java程式設計師面試指南等乾貨資源)
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69906029/viewspace-2653962/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 走進JavaWeb技術世界4:Servlet 工作原理詳解JavaWebServlet
- 走進JavaWeb技術世界3:JDBC的進化與連線池技術JavaWebJDBC
- 走進JavaWeb技術世界1:JavaWeb的由來和基礎知識JavaWeb
- 走進JavaWeb技術世界5:初探Tomcat的HTTP請求過程JavaWebTomcatHTTP
- 從 flutter demo走進flutter 世界Flutter
- 走進Spring Cloud Alibaba的世界SpringCloud
- 走進Oracle世界Oracle
- 帶你走進 HarmonyOS:前端如何迎接新技術的到來前端
- JavaWeb從入門到入土第10天JavaWeb
- 從Oracle DBA出發,走進GaussDB的世界 - 雲和恩墨大講堂GaussDB專題Oracle
- 從技術到管理
- 從滴水到怒海:方舟編譯器如何影響技術世界?編譯
- 走進AI影像生成核心技術 - DiffusionAI
- 【C#——走進你的世界】C#
- 從圖靈原創談起,帶你走進國產技術書的時代圖靈
- 即將到來並可能改變世界的10項技術
- 《持續交付》走進百度技術沙龍
- 前端技術 | 從Flux到Redux前端Redux
- [] == ![],走進==隱式轉換的世界
- 走進ADAMoracle預言機的世界Oracle
- 極客拯救世界:10項即將到來並可能改變世界的技術
- 從古代文學到雲端技術
- 技術攻關:從零到精通
- javaweb中應用urlrewrite技術JavaWeb
- 走進C++世界------臨時物件使用C++物件
- 從《使命召喚》到《我的世界》,光線追蹤技術如何改變遊戲?遊戲
- 阿朱:從50到5000,從技術到人(圖靈訪談)圖靈
- JavaWeb——JSP呼叫資料庫、JavaBean、MVC模式JavaWebJS資料庫BeanMVC模式
- 從小白到專家 PG技術大講堂 - Part 2:PG原始碼安裝原始碼
- 帶你走進memcache,老牌記憶體快取技術記憶體快取
- 從babel講到ASTBabelAST
- 帶您走進松本行弘的程式世界
- 走進Linux的世界,需要怎麼做Linux
- 一張圖帶你走進Retrofit原始碼世界原始碼
- Miox帶你走進動態路由的世界路由
- 從小白到專家 PostgreSQL技術大講堂 - Part 5:PG資料庫結構SQL資料庫
- 從 0 到 1:我的 Flutter 技術實踐 | 掘金技術徵文Flutter
- 【漫畫講技術】CSS系列漫畫教程(6-10講)CSS