Spring AOP

来源:https://www.cnblogs.com/chy18883701161/archive/2019/07/04/11135435.html
-Advertisement-
Play Games

目錄 AOP簡介 Spring AOP的2種代理 JDK動態代理 CGLIB代理 AOP簡介 AOP全稱Aspect-Oriented Programming,即面向切麵編程,它是面向對象編程(OOP)的一種補充。 在通常的業務處理中,都會進行事務處理、日誌記錄等操作,比如: 這是一個操作用戶的類, ...


 

目錄

AOP簡介

Spring  AOP的2種代理

 

 

 

AOP簡介

AOP全稱Aspect-Oriented  Programming,即面向切麵編程,它是面向對象編程(OOP)的一種補充。

 

在通常的業務處理中,都會進行事務處理、日誌記錄等操作,比如:

 1 class  User{
 2     public void addUser(){
 3         ......  //添加用戶
 4         ....... //記錄一條日誌:xxx時間添加xxx用戶,操作者:xxx,操作結果:xxx
 5     }
 6 
 7     public  void  alterUser(){
 8         .......  //修改用戶
 9         ........//記錄一條日誌:xxx時間修改xxx用戶,操作者:xxx,操作結果:xxx
10     }
11 
12     public void  deleteUser(){
13         .......//刪除用戶
14         .......//記錄一條日誌:xxx時間刪除xxx用戶,操作者:xxx,操作結果:xxx
15 }

這是一個操作用戶的類,是對用戶的抽象,日誌操作和用戶操作其實沒有半毛錢關係,上面的抽象並不好,把用戶操作和日誌操作雜糅在一起,應該把日誌操作分離出去,這樣才符合OOP的編程思想。

而且後期不好維護、升級,比如後面要修改日誌操作,你找到User類,在addUser()中一部分是用戶操作,一部分是日誌操作,你要先找到哪些是日誌操作,然後改。後面的方法也是如此,很繁瑣。

 

AOP解決了此問題。AOP是一種新的編程思想,是OOP的一種補充。OOP專心負責核心業務,AOP負責其它雜七雜八的業務。

OOP好比是經理,AOP好比是助理。原先所有事兒,什麼批文件、見客戶、通知下級來開會、向下級傳達指示,所有事兒都是自己做,很繁瑣,搞得精疲力竭,還容易出問題。

現在招了助理AOP,總經理OOP可以專心處理核心的業務,批示下文件、見見客戶就行了。傳遞指示、通知下級開會,這些事兒助理AOP來做。分工明確,效率

高很多。

 

 

這些操作往往可以被多個類使用的,所以叫做一個切麵(Aspect)。

 

目前最流行的AOP框架有2個:Spring  AOP和AspectJ。

 

 

 

 

Spring  AOP

在Spring AOP中,spring是通過代理(proxy)實現的AOP。有2種代理方式:JDK動態代理、CGLIB代理。

 

JDK動態代理

1、新建包jdk_proxy,用來寫代理類、被代理類。包下新建UserInterface介面

1 public interface UserInterface {
2     public void addUser();
3     public void alterUser();
4     public void deleteUser();
5 }

 

 

包下新建一個實現類User

 1 public class User implements UserInterface {
 2     @Override
 3     public void addUser() {
 4         //模擬添加用戶
 5         System.out.println("正在添加用戶");
 6         System.out.println("添加用戶成功");
 7     }
 8 
 9     @Override
10     public void alterUser() {
11         //模擬修改用戶信息
12         System.out.println("正在修改用戶信息");
13         System.out.println("修改用戶信息成功");
14     }
15 
16     @Override
17     public void deleteUser() {
18         //模擬刪除用戶
19         System.out.println("正在刪除用戶");
20         System.out.println("刪除用戶成功");
21     }
22 }

 

這些是要被代理的類。

 

 

2、新建包aspect,用來寫切麵中要使用方法(類)。包下新建類MyAspect

 1 public class MyAspect {
 2     //模擬檢查許可權
 3     public boolean checkPermission(){
 4         System.out.println("正在檢查許可權");
 5         System.out.println("許可權已夠");
 6         return true;
 7     }
 8 
 9     //模擬日誌
10     public void log(){
11         System.out.println("正在寫入日誌");
12         System.out.println("xxx時間,xxx進行xxx操作,操作結果:xxx");
13         System.out.println("日誌寫入完畢");
14     }
15 }

 

 

 

3、在jdk_proxy包下,新建JdkProxy類,要實現InvocationHandler介面(只有invoke()方法)

 1 public class JdkProxy implements InvocationHandler {
 2     //聲明目標介面的實例
 3     private UserInterface user;
 4     
 5     //創建代理方法,參數是目標介面的實例
 6     public Object createProxy(UserInterface user){
 7         this.user=user;   //初始化目標介面實例
 8 
 9         ClassLoader classLoader=JdkProxy.class.getClassLoader();  //獲取當前類的類載入器,當前類類名.class.getClassLoader()
10         Class[] classArr=user.getClass().getInterfaces();  //獲取目標介面實例實現的全部介面
11 
12         //參數:當前類的類載入器,目標介面實例實現的所有介面,當前類的實例
13         return Proxy.newProxyInstance(classLoader,classArr,this);
14     }
15 
16     @Override
17     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
18         //聲明切麵
19         MyAspect myAspect=new MyAspect();
20 
21         //前增強,執行切麵中的方法,在執行目標類中的方法之前做一些操作,比如檢查許可權。根據需要選用。
22         myAspect.checkPermission();
23 
24         //執行目標類中的方法。比如addUser()。第一個參數目標對象,第二個是固定的
25         Object object=method.invoke(user,args);
26 
27         //後增強。執行切麵中的方法,在執行目標類中的方法之後做一些操作,比如記錄日誌。根據需要選用。
28         myAspect.log();
29 
30         return object;
31     }
32 }

 

這是代理類,用來代理User類/UserInterface介面。

 

 

4、 新建一個test包,用來寫測試類。包下新建類Test

 1 public class Test {
 2     public static void main(String[] args) {
 3         //JdkProxy的實例
 4         JdkProxy jdkProxy=new JdkProxy();
 5 
 6         //創建目標對象
 7         UserInterface user=new User();
 8 
 9         //通過JdkProxy類的實例動態創建user的代理,因為返回值是Object,需要強制類型轉換,必須用目標介面轉換,不能用實現類轉換
10         UserInterface userProxy=(UserInterface) jdkProxy.createProxy(user);
11 
12         //通過代理調用方法,會自動調用OOP、AOP中的相關方法。
13         userProxy.addUser();
14     }
15 }

 

 

5、運行,看到控制台輸出如下

正在檢查許可權
許可權已夠
正在添加用戶
添加用戶成功
正在寫入日誌
xxx時間,xxx進行xxx操作,操作結果:xxx
日誌寫入完畢

已自動調用AOP(前增強+後增強)、OOP(業務本身)中的方法。

 

 

 

模型分析

 

 

AOP術語

  • Aspect(切麵):用來寫AOP中要用的方法,比如上例中的MyAspect類。
  • Pointcut(切入點):AOP、OOP交匯處,比如addUser()、alterUser()、deleteUser(),這三個方法是OOP中的方法,但使用時還會調用AOP中檢查許可權、記錄日誌的方法,這三個方法就是AOP切入OOP的切入點。
  • Joinpoint(連接點):即切入點+AOP處理的點,比如checkPermission()、addUser()、log()就是三個連接點。
  • Advice(通知/增強):英文意為建議,即做一些其他操作。比如前增強checkPermission()、後增強log()
  • Target  Object(目標對象):被代理的對象,比如UserInterface介面/User類的實例
  • Proxy(代理):即上例的userProxy
  • Weaving(織入):將AOP植入到OOP中,比如上例的JdkProxy類。

 

 

 

 

CGLIB代理

因為JDK動態代理的JdkProxy類中的createProxy()方法中 Class[] classArr=user.getClass().getInterfaces(); //獲取目標介面實例實現的全部介面 ,要用到目標對象的所實現的全部介面,就是說被代理的OOP的核心業務類必須要實現介面。

如果被代理的類沒有實現介面,則可以使用CGLIB代理。

 

1、新建一個cglib包,用來寫代理類、被代理類。包下新建User類(被代理類),不必實現介面

 1 public class User{
 2     public void addUser() {
 3         //模擬添加用戶
 4         System.out.println("正在添加用戶");
 5         System.out.println("添加用戶成功");
 6     }
 7 
 8     public void alterUser() {
 9         //模擬修改用戶信息
10         System.out.println("正在修改用戶信息");
11         System.out.println("修改用戶信息成功");
12     }
13 
14     public void deleteUser() {
15         //模擬刪除用戶
16         System.out.println("正在刪除用戶");
17         System.out.println("刪除用戶成功");
18     }
19 }

 

 

 

2、新建包aspect,包下新建切麵類MyAspect

 1 public class MyAspect {
 2     //模擬檢查許可權
 3     public boolean checkPermission(){
 4         System.out.println("正在檢查許可權");
 5         System.out.println("許可權已夠");
 6         return true;
 7     }
 8 
 9     //模擬日誌
10     public void log(){
11         System.out.println("正在寫入日誌");
12         System.out.println("xxx時間,xxx進行xxx操作,操作結果:xxx");
13         System.out.println("日誌寫入完畢");
14     }
15 }

 

 

 

3、在cglib包下新建CglibProxy類(代理類),需實現MethodInterceptor介面(只有intercept()方法)。註意是org.springframework.cglib.proxy.MethodInterceptor介面,不是其他包下的MethodInterceptor介面。

 1 public class CglibProxy implements MethodInterceptor {
 2     //創建代理,參數是Object類型
 3     public Object createProxy(Object target){
 4         Enhancer enhancer=new Enhancer();   //創建一個動態類對象
 5         enhancer.setSuperclass(target.getClass());  //將這個動態類對象的父類/基類設置為目標類(需要增強的類)
 6         enhancer.setCallback(this);  //設置回調
 7         return  enhancer.create();  //返回創建的代理
 8     }
 9 
10     @Override
11     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
12         //創建切麵實例
13         MyAspect myAspect=new MyAspect();
14 
15         //前增強
16         myAspect.checkPermission();
17 
18         //執行目標方法,參數:形參表的第一個參數、第三個參數
19         Object object=methodProxy.invokeSuper(o,objects);
20 
21         //後增強
22         myAspect.log();
23 
24         //返回代理對象
25         return object;
26     }
27 }

 

 

 

4、新建包test,包下新建測試類Test

 1 public class Test {
 2     public static void main(String[] args) {
 3         //創建CglibProxy的實例
 4         CglibProxy cglibProxy=new CglibProxy();
 5 
 6         //創建目標對象
 7         User user=new User();
 8 
 9         //通過CglibProxy類的實例創建user的代理,因為返回值是Object,需要強制類型轉換,
10         User userProxy=(User)cglibProxy.createProxy(user);
11 
12         //通過代理調用方法,會自動調用OOP、AOP中的相關方法。
13         userProxy.addUser();
14     }
15 }

 

 

 

5、運行,控制台輸出如下

正在檢查許可權
許可權已夠
正在添加用戶
添加用戶成功
正在寫入日誌
xxx時間,xxx進行xxx操作,操作結果:xxx
日誌寫入完畢

 

 

 

說明

  • JDK動態代理需要目標類(被代理的類)實現介面,CGLIB代理不需要目標類實現介面。
  • 需要spring-aop.jar的支持(Spring自帶的)。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ​ 1.python的歷史 python2和python3的區別 python2 源碼不統一,重覆代碼 python 源碼統一,沒有重覆代碼 2004 Django框架的誕生 2.python是編程語言 3.python的種類 4.變數 變數定義的規則: 一個變數名在記憶體中只有一個。 5.常量 變數 ...
  • 一、Redis集群簡介 1、RedisCluster概念 Redis的分散式解決方案,在3.0版本後推出的方案,有效地解決了Redis分散式的需求,當一個服務宕機可以快速的切換到另外一個服務。redis cluster主要是針對海量數據+高併發+高可用的場景。 二、與SpringBoot2.0整合 ...
  • 下載地址 ...
  • 提交leetcode的時候遇到了問題,一直說訪問越界,但仔仔細細檢查n多遍,就是檢查不出來。 因為我用到了count全局變數,自加一來表明當前數組訪問的位置, 後來突然想到,是不是在運行的時候沒有對這個全局變數清零…… 果然,清零之後就可以了……已經3:47了,這裡先上代碼,明天再詳細說吧…… ch ...
  • 1.什麼是Redis? Redis(Remote Dictionary Server)遠程字典伺服器。 是完全開源免費的,用C語言編寫的,遵守BSD協議,是一個高性能的(key/value)分散式記憶體資料庫,基於記憶體運行並支持持久化的NoSql資料庫,是當前最熱門的NoSql資料庫之一,也被人們稱為 ...
  • 最近公司需要開發一個公司內部使用的快遞下單系統,給我的開發任務中有一個生成電子面單功能,為了下單時更方便,利用此功能使用快遞公司給我們的印表機直接列印出電子面單,剛接到這個任務時我想這應該很簡單,不就是做一個表格列印出來嗎,原本以為使用excel或者word等工具直接生成一個文檔,後來經理說不用ex ...
  • 0x00 問題重現 VS COde 打開 .go 文件會自動安裝插件,但是出現了一些工具的下載失敗。 換上全局代理也無法下載。 找了許多教程,但可能由於一些版本的問題,目錄已經變更了,導致吾卡在這裡許久。尤其是 github.com/stamblerre/gocode 。 0x01 解決 MacOS ...
  • 一、前言 眾所周知,spring最核心的兩個功能是aop和ioc,即面向切麵和控制反轉。本文會講一講SpringBoot如何使用AOP實現面向切麵的過程原理。 二、何為aop ​ aop全稱 ,面向切麵,AOP主要實現的目的是針對業務處理過程中的切麵進行提取,它所面對的是處理過程中的某個步驟或階段, ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...