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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

dao接口有什么好处_Java后端精选技术:我们为什么要使用AOP?

發(fā)布時間:2025/4/5 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dao接口有什么好处_Java后端精选技术:我们为什么要使用AOP? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

之前寫了一篇文章Spring3:AOP,是當時學習如何使用Spring AOP的時候寫的,比較基礎。這篇文章最后的推薦以及回復認為我寫的對大家有幫助的評論有很多,但是現(xiàn)在從我個人的角度來看,這篇文章寫得并不好,甚至可以說是沒有太多實質性的內容,因此這些推薦和評論讓我覺得受之有愧。

基于以上原因,更新一篇文章,從最基礎的原始代碼-->使用設計模式(裝飾器模式與代理)-->使用AOP三個層次來講解一下為什么我們要使用AOP,希望這篇文章可以對網友朋友們有益。

原始代碼的寫法

既然要通過代碼來演示,那必須要有例子,這里我的例子為:

有一個接口Dao有insert、delete、update三個方法,在insert與update被調用的前后,打印調用前的毫秒數與調用后的毫秒數。

首先定義一個Dao接口:

public interface Dao { public void insert(); public void delete(); public void update(); }

然后定義一個實現(xiàn)類DaoImpl:

最原始的寫法,我要在調用insert()與update()方法前后分別打印時間,就只能定義一個新的類包一層,在調用insert()方法與update()方法前后分別處理一下,新的類我命名為ServiceImpl,其實現(xiàn)為:

這是最原始的寫法,這種寫法的缺點也是一目了然:

  • 方法調用前后輸出時間的邏輯無法復用,如果有別的地方要增加這段邏輯就得再寫一遍
  • 如果Dao有其它實現(xiàn)類,那么必須新增一個類去包裝該實現(xiàn)類,這將導致類數量不斷膨脹
  • 使用裝飾器模式

    接著我們使用上設計模式,先用裝飾器模式,看看能解決多少問題。裝飾器模式的核心就是實現(xiàn)Dao接口并持有Dao接口的引用,我將新增的類命名為LogDao,其實現(xiàn)為:

    在使用的時候,可以使用"Dao dao = new LogDao(new DaoImpl())"的方式,這種方式的優(yōu)點為:

    • 透明,對調用方來說,它只知道Dao,而不知道加上了日志功能
    • 類不會無限膨脹,如果Dao的其它實現(xiàn)類需要輸出日志,只需要向LogDao的構造函數中傳入不同的Dao實現(xiàn)類即可。

    不過這種方式同樣有明顯的缺點,缺點為:

    • 輸出日志的邏輯還是無法復用。
    • 輸出日志的邏輯與代碼有耦合,如果我要對delete()方法前后同樣輸出時間,需要修改LogDao。

    但是,這種做法相比最原始的代碼寫法,已經有了很大的改進。

    使用代理模式

    接著我們使用代理模式嘗試去實現(xiàn)最原始的功能,使用代理模式,那么我們就要定義一個InvocationHandler,我將它命名為LogInvocationHandler,其實現(xiàn)為:

    其調用方式很簡單,我寫一個main函數:

    結果就不演示了,這種方式的優(yōu)點為:

    • 輸出日志的邏輯被復用起來,如果要針對其他接口用上輸出日志的邏輯,只要在newProxyInstance的時候的第二個參數增加Class數組中的內容即可。

    這種方式的缺點為:

    • JDK提供的動態(tài)代理只能針對接口做代理,不能針對類做代理。
    • 代碼依然有耦合,如果要對delete方法調用前后打印時間,得在LogInvocationHandler中增加delete方法的判斷。

    使用CGLIB

    接著看一下使用CGLIB的方式,使用CGLIB只需要實現(xiàn)MethodInterceptor接口即可:

    代碼調用方式為:

    使用CGLIB解決了JDK的Proxy無法針對類做代理的問題,但是這里要專門說明一個問題:使用裝飾器模式可以說是對使用原生代碼的一種改進,使用Java代理可以說是對于使用裝飾器模式的一種改進,但是使用CGLIB并不是對于使用Java代理的一種改進。

    前面的可以說改進是因為使用裝飾器模式比使用原生代碼更好,使用Java代理又比使用裝飾器模式更好,但是Java代理與CGLIb的對比并不能說改進,因為使用CGLIB并不一定比使用Java代理更好,這兩種各有優(yōu)缺點,像Spring框架就同時支持Java Proxy與CGLIB兩種方式。

    從目前看來代碼又更好了一些,但是我認為還有兩個缺點:

    • 無論使用Java代理還是使用CGLIB,編寫這部分代碼都稍顯麻煩。
    • 代碼之間的耦合還是沒有解決,像要針對delete()方法加上這部分邏輯就必須修改代碼。

    使用AOP

    最后來看一下使用AOP的方式,首先定義一個時間處理類,我將它命名為TimeHandler:

    到第8行的代碼與第12行的代碼分別打印方法開始執(zhí)行時間與方法結束執(zhí)行時間。我這里寫得稍微復雜點,使用了的寫法,其實也可以拆分為與兩種,這個看個人喜好。

    這里多說一句,切面方法printTime本身可以不用定義任何的參數,但是有些場景下需要獲取調用方法的類、方法簽名等信息,此時可以在printTime方法中定義JointPoint,Spring會自動將參數注入,可以通過JoinPoint獲取調用方法的類、方法簽名等信息。

    由于這里我用的,要保證方法的調用,這樣才能在方法調用前后輸出時間,因此不能直接使用JoinPoint,因為JoinPoint沒法保證方法調用。此時可以使用ProceedingJoinPoint,ProceedingPointPoint的proceed()方法可以保證方法調用,但是要注意一點,ProceedingJoinPoint只能和搭配,換句話說,如果aop.xml中配置的是,然后printTime的方法參數又是ProceedingJoinPoint的話,Spring容器啟動將報錯。

    接著看一下aop.xml的配置:

    我不大會寫expression,也懶得去百度了,因此這里就攔截Dao下的所有方法了。測試代碼很簡單:

    結果就不演示了。到此我總結一下使用AOP的幾個優(yōu)點:

  • 切面的內容可以復用,比如TimeHandler的printTime方法,任何地方需要打印方法執(zhí)行前的時間與方法執(zhí)行后的時間,都可以使用TimeHandler的printTime方法
  • 避免使用Proxy、CGLIB生成代理,這方面的工作全部框架去實現(xiàn),開發(fā)者可以專注于切面內容本身
  • 代碼與代碼之間沒有耦合,如果攔截的方法有變化修改配置文件即可
  • 下面用一張圖來表示一下AOP的作用:

    我們傳統(tǒng)的編程方式是垂直化的編程,即A-->B-->C-->D這么下去,一個邏輯完畢之后執(zhí)行另外一段邏輯。但是AOP提供了另外一種思路,它的作用是在業(yè)務邏輯不知情(即業(yè)務邏輯不需要做任何的改動)的情況下對業(yè)務代碼的功能進行增強,這種編程思想的使用場景有很多,例如事務提交、方法執(zhí)行之前的權限檢測、日志打印、方法調用事件等等。

    AOP使用場景舉例

    上面的例子純粹為了演示使用,為了讓大家更加理解AOP的作用,這里以實際場景作為例子。

    第一個例子,我們知道MyBatis的事務默認是不會自動提交的,因此在編程的時候我們必須在增刪改完畢之后調用SqlSession的commit()方法進行事務提交,這非常麻煩,下面利用AOP簡單寫一段代碼幫助我們自動提交事務(這段代碼我個人測試過可用):

    這種場景下我們要使用的aop標簽為,即切在方法調用之后。

    這里我做了一個SqlSessionThreadLocalUtil,每次打開會話的時候,都通過SqlSessionThreadLocalUtil把當前會話SqlSession放到ThreadLocal中,看到通過TransactionHandler,可以實現(xiàn)兩個功能:

  • insert、update、delete操作事務自動提交
  • 對SqlSession進行close(),這樣就不需要在業(yè)務代碼里面關閉會話了,因為有些時候我們寫業(yè)務代碼的時候會忘記關閉SqlSession,這樣可能會造成內存句柄的膨脹,因此這部分切面也一并做了
  • 整個過程,業(yè)務代碼是不知道的,而TransactionHandler的內容可以充分再多處場景下進行復用。

    第二個例子是權限控制的例子,不管是從安全角度考慮還是從業(yè)務角度考慮,我們在開發(fā)一個Web系統(tǒng)的時候不可能所有請求都對所有用戶開放,因此這里就需要做一層權限控制了,大家看AOP作用的時候想必也肯定會看到AOP可以做權限控制,這里我就演示一下如何使用AOP做權限控制。我們知道原生的Spring MVC,Java類是實現(xiàn)Controller接口的,基于此,利用AOP做權限控制的大致代碼如下(這段代碼純粹就是一段示例,我構建的Maven工程是一個普通的Java工程,因此沒有驗證過):

    毫無疑問這種場景下我們要使用的aop標簽為。這里我寫得很簡單,獲取當前用戶id與請求路徑,根據這兩者,判斷該用戶是否有權限訪問該請求,大家明白意思即可。

    后記

    文章演示了從原生代碼到使用AOP的過程,一點一點地介紹了每次演化的優(yōu)缺點,最后以實際例子分析了AOP可以做什么事情。

    之前的那篇AOP入門的文章Spring3:AOP再結合上這篇文章,希望可以真正對網友朋友們有益。

    總結

    以上是生活随笔為你收集整理的dao接口有什么好处_Java后端精选技术:我们为什么要使用AOP?的全部內容,希望文章能夠幫你解決所遇到的問題。

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