成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

AOP面向切面編程

開發 后端
AOP(Aspect-Oriented Programming,面向切面的編程),它是可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。它是一種新的方法論,它是對傳統OOP編程的一種補充。

AOP(Aspect-Oriented Programming,面向切面的編程),它是可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術。它是一種新的方法論,它是對傳統OOP編程的一種補充。

OOP是關注將需求功能劃分為不同的并且相對獨立,封裝良好的類,并讓它們有著屬于自己的行為,依靠繼承和多態等來定義彼此的關系;AOP是希望能夠將通用需求功能從不相關的類當中分離出來,能夠使得很多類共享一個行為,一旦發生變化,不必修改很多類,而只需要修改這個行為即可。

AOP是使用切面(aspect)將橫切關注點模塊化,OOP是使用類將狀態和行為模塊化。在OOP的世界中,程序都是通過類和接口組織的,使用它們實現程序的核心業務邏輯是十分合適。但是對于實現橫切關注點(跨越應用程序多個模塊的功能需求)則十分吃力,比如日志記錄,驗證。

  1. /*計算器接口*/ 
  2. public interface Calculator  
  3. {  
  4.     public double add(double num1, double num2) throws Exception;  
  5.     public double sub(double num1, double num2) throws Exception;  
  6.     public double div(double num1, double num2) throws Exception;  
  7.     public double mul(double num1, double num2) throws Exception;  
  1. /*計算器接口的實現類*/ 
  2. public class ArithmeticCalculator implements Calculator  
  3. {  
  4.     @Override 
  5.     public double add(double num1, double num2)  
  6.     {  
  7.         double result = num1 + num2;  
  8.         return result;  
  9.     }  
  10.  
  11.     @Override 
  12.     public double sub(double num1, double num2)  
  13.     {  
  14.         double result = num1 - num2;  
  15.         return result;  
  16.     }  
  17.  
  18.     /*示意代碼 暫時不考慮除數0的情況*/ 
  19.     @Override 
  20.     public double div(double num1, double num2)  
  21.     {  
  22.         double result = num1 / num2;  
  23.         return result;  
  24.     }  
  25.  
  26.     @Override 
  27.     public double mul(double num1, double num2)  
  28.     {  
  29.         double result = num1 * num2;  
  30.         return result;  
  31.     }  

大多數應用程序都有一個通用的需求,即在程序運行期間追蹤正在發生的活動。為了給計算機添加日志功能,ArithmeticCalculator類改變如下:

  1. /*計算器接口的實現類,添加記錄日志功能*/ 
  2. public class ArithmeticCalculator implements Calculator  
  3. {  
  4.     @Override 
  5.     public double add(double num1, double num2)  
  6.     {  
  7.         System.out.println("the method [add()]"+"begin with args ("+num1+","+num2+")");  
  8.         double result = num1 + num2;  
  9.         System.out.println("the method [add()]"+"end with result ("+result+")");  
  10.           
  11.         return result;  
  12.     }  
  13.  
  14.     @Override 
  15.     public double sub(double num1, double num2)  
  16.     {  
  17.         System.out.println("the method [sub()]"+"begin with args ("+num1+","+num2+")");  
  18.         double result = num1 - num2;  
  19.         System.out.println("the method [sub()]"+"end with result ("+result+")");  
  20.           
  21.         return result;  
  22.     }  
  23.  
  24.     /*示意代碼 暫時不考慮除數0的情況*/ 
  25.     @Override 
  26.     public double div(double num1, double num2)  
  27.     {  
  28.         System.out.println("the method [div()]"+"begin with args ("+num1+","+num2+")");  
  29.         double result = num1 / num2;  
  30.         System.out.println("the method [div()]"+"end with result ("+result+")");  
  31.           
  32.         return result;  
  33.     }  
  34.  
  35.     @Override 
  36.     public double mul(double num1, double num2)  
  37.     {  
  38.         System.out.println("the method [mul()]"+"begin with args ("+num1+","+num2+")");  
  39.         double result = num1 * num2;  
  40.         System.out.println("the method [mul()]"+"end with result ("+result+")");  
  41.           
  42.         return result;  
  43.     }  

若ArithmeticCalculator規定只能計算正數時,又需要添加參數驗證方法:

  1. /*計算器接口的實現類,添加記錄日志功能*/ 
  2. public class ArithmeticCalculator implements Calculator  
  3. {  
  4.     @Override 
  5.     public double add(double num1, double num2) throws Exception  
  6.     {  
  7.         this.argsValidatior(num1);  
  8.         this.argsValidatior(num2);  
  9.           
  10.          /*同上*/ 
  11.     }  
  12.  
  13.     @Override 
  14.     public double sub(double num1, double num2) throws Exception  
  15.     {  
  16.         this.argsValidatior(num1);  
  17.         this.argsValidatior(num2);  
  18.           
  19.          /*同上*/ 
  20.     }  
  21.  
  22.     /*示意代碼 暫時不考慮除數0的情況*/ 
  23.     @Override 
  24.     public double div(double num1, double num2) throws Exception  
  25.     {  
  26.         this.argsValidatior(num1);  
  27.         this.argsValidatior(num2);  
  28.           
  29.          /*同上*/ 
  30.     }  
  31.  
  32.     @Override 
  33.     public double mul(double num1, double num2) throws Exception  
  34.     {  
  35.         this.argsValidatior(num1);  
  36.         this.argsValidatior(num2);  
  37.           
  38.         /*同上*/ 
  39.     }  
  40.       
  41.     private void argsValidatior(double arg)throws Exception  
  42.     {  
  43.         if(arg < 0)  
  44.             throw new Exception("參數不能為負數");  
  45.     }  

上面的程序一個很直觀的特點就是,好多重復的代碼,并且當加入越來越多的非業務需求(例如日志記錄和參數驗證),原有的計算器方法變得膨脹冗長。這里有一件非常痛苦的事情,無法使用原有的編程方式將他們模塊化,從核心業務中提取出來。例如日志記錄和參數驗證,AOP里將他們稱為橫切關注點(crosscutting concern),它們屬于系統范圍的需求通常需要跨越多個模塊。

在使用傳統的面向對象的編程方式無法理想化的模塊化橫切關注點,程序員不能不做的就是將這些橫切關注點放置在每一個模塊里與核心邏輯交織在一起,這將會導致橫切關注點在每一個模塊里到處存在。使用非模塊化的手段實現橫切關注將會導致,代碼混亂,代碼分散,代碼重復。你想想看如果日志記錄需要換一種顯示方式,那你要改多少代碼,一旦漏掉一處(概率很高),將會導致日志記錄不一致。這樣的代碼很維護。種種原因表明,模塊只需要關注自己原本的功能需求,需要一種方式來將橫切關注點沖模塊中提取出來。

忍無可忍的大牛們提出了AOP,它是一個概念,一個規范,本身并沒有設定具體語言的實現,也正是這個特性讓它變的非常流行,現在已經有許多開源的AOP實現框架了。本次不是介紹這些框架的,我們將不使用這些框架,而是使用底層編碼的方式實現最基本的AOP解決上面例子出現的問題。AOP實際是GoF設計模式的延續,設計模式孜孜不倦追求的是調用者和被調用者之間的解耦,AOP可以說也是這種目標的一種實現。AOP可以使用"代理模式"來實現。

代理模式的原理是使用一個代理將對象包裝起來,然后用該代理對象取代原始的對象,任何對原始對象的調用首先要經過代理。代理對象負責決定是否以及何時將方法調用信息轉發到原始對象上。與此同時,圍繞著每個方法的調用,代理對象也可以執行一些額外的工作。可以看出代理模式非常適合實現橫切關注點。

由于本人只了解Java,所以姑且認為代理模式有兩種實現方式,一種是靜態代理、另一種是動態代理。他們的區別在于編譯時知不知道代理的對象是誰。在模塊比較多的系統中,靜態代理是不合適也非常低效的,因為靜態代理需要專門為每一個接口設計一個代理類,系統比較大成百上千的接口是很正常的,靜態代理模式太消耗人力了。動態代理是JDK所支持的代理模式,它可以非常好的實現橫切關注點。

  1. /*使用動態代理需要實現InvocationHandler接口*/ 
  2. public class ArithmeticCalculatorInvocationHandler implements InvocationHandler  
  3. {  
  4.     /*要代理的對象,動態代理只有在運行時才知道代理誰,所以定義為Object類型,可以代理任意對象*/ 
  5.     private Object target = null;  
  6.       
  7.     /*通過構造函數傳入原對象*/ 
  8.     public ArithmeticCalculatorInvocationHandler(Object target)  
  9.     {  
  10.         this.target = target;  
  11.     }  
  12.  
  13.     /*InvocationHandler接口的方法,proxy表示代理,method表示原對象被調用的方法,args表示方法的參數*/ 
  14.     @Override 
  15.     public Object invoke(Object proxy, Method method, Object[] args)  
  16.             throws Throwable  
  17.     {  
  18.         /*原對象方法調用前處理日志信息*/ 
  19.         System.out.println("the method ["+method.getName()+"]"+"begin with args ("+Arrays.toString(args)+")");  
  20.           
  21.         Object result = method.invoke(this.target, args);  
  22.           
  23.         /*原對象方法調用后處理日志信息*/ 
  24.         System.out.println("the method ["+method.getName()+"]"+"end with result ("+result+")");  
  25.           
  26.         return result;  
  27.     }  
  28.       
  29.     /*獲取代理類*/ 
  30.     public Object getProxy()  
  31.     {  
  32.         return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.getClass().getInterfaces(), this);  
  33.     }  

場景類調用:

  1. public class Client  
  2. {  
  3.     public static void main(String[] args) throws Exception  
  4.     {  
  5.         /*獲得代理*/ 
  6.         Calculator arithmeticCalculatorProxy = (Calculator)new ArithmeticCalculatorInvocationHandler(  
  7.                  new ArithmeticCalculator()).getProxy();  
  8.  
  9.         /*調用add方法*/ 
  10.         arithmeticCalculatorProxy.add(1010);  
  11.     }  

控制臺的輸出:

  1. the method [add]begin with args ([10.010.0])  
  2. the method [add]end with result (20.0

可以看到使用動態代理實現了橫切關注點。

若需要添加參數驗證功能,只需要再創建一個參數驗證代理即可:

  1. public class ArithmeticCalculatorArgsInvocationHandler implements 
  2.         InvocationHandler  
  3. {  
  4.     /*要代理的對象,動態代理只有在運行時才知道代理誰,所以定義為Object類型,可以代理任意對象*/ 
  5.     private Object target = null;  
  6.       
  7.     /*通過構造函數傳入原對象*/ 
  8.     public ArithmeticCalculatorArgsInvocationHandler(Object target)  
  9.     {  
  10.         this.target = target;  
  11.     }  
  12.  
  13.     /*InvocationHandler接口的方法,proxy表示代理,method表示原對象被調用的方法,args表示方法的參數*/ 
  14.     @Override 
  15.     public Object invoke(Object proxy, Method method, Object[] args)  
  16.             throws Throwable  
  17.     {  
  18.         System.out.println("begin valid method ["+method.getName()+"] with args "+Arrays.toString(args));  
  19.           
  20.         for(Object arg : args)  
  21.         {  
  22.             this.argValidtor((Double)arg);  
  23.         }  
  24.           
  25.         Object result = method.invoke(this.target, args);  
  26.           
  27.         return result;  
  28.     }  
  29.       
  30.     /*獲取代理類*/ 
  31.     public Object getProxy()  
  32.     {  
  33.         return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);  
  34.     }  
  35.       
  36.     private void argValidtor(double arg) throws Exception  
  37.     {  
  38.         if(arg < 0)  
  39.             throw new Exception("參數不能為負數!");  
  40.     }  

場景類調用:

  1. public class Client  
  2. {  
  3.     public static void main(String[] args) throws Exception  
  4.     {  
  5.         /*獲得代理*/ 
  6.         Calculator arithmeticCalculatorProxy = (Calculator)new ArithmeticCalculatorInvocationHandler(  
  7.                  new ArithmeticCalculator()).getProxy();  
  8.           
  9.         Calculator argValidatorProxy = (Calculator)new ArithmeticCalculatorArgsInvocationHandler(arithmeticCalculatorProxy).getProxy();  
  10.  
  11.         /*調用add方法*/ 
  12.         argValidatorProxy.add(1010);  
  13.     }  

 控制臺輸出:

  1. begin valid method [add] with args [10.010.0]  
  2. the method [add]begin with args ([10.010.0])  
  3. the method [add]end with result (20.0

輸入一個負數數據:

  1. public class Client  
  2. {  
  3.     public static void main(String[] args) throws Exception  
  4.     {  
  5.         /*獲得代理*/ 
  6.         Calculator arithmeticCalculatorProxy = (Calculator)new ArithmeticCalculatorInvocationHandler(  
  7.                  new ArithmeticCalculator()).getProxy();  
  8.           
  9.         Calculator argValidatorProxy = (Calculator)new ArithmeticCalculatorArgsInvocationHandler(arithmeticCalculatorProxy).getProxy();  
  10.  
  11.         /*調用add方法*/ 
  12.         argValidatorProxy.add(-1010);  
  13.     }  

控制臺輸出:

  1. begin valid method [add] with args [-10.010.0]  
  2. Exception in thread "main" java.lang.Exception: 參數不能為負數!  
  3.     at com.beliefbetrayal.aop.ArithmeticCalculatorArgsInvocationHandler.argValidtor(ArithmeticCalculatorArgsInvocationHandler.java:46)  
  4.     at com.beliefbetrayal.aop.ArithmeticCalculatorArgsInvocationHandler.invoke(ArithmeticCalculatorArgsInvocationHandler.java:29)  
  5.     at $Proxy0.add(Unknown Source)  
  6.     at com.beliefbetrayal.aop.Client.main(Client.java:14

 


不知道你有沒有使用過Struts2,這個結構和Struts2的攔截器非常相似,一個個Action對象好比我們的原對象業務核心,一個個攔截器好比是這里的代理,通用的功能實現成攔截器,讓Action可以共用,Struts2的攔截器也是AOP的優秀實現。

原文鏈接:http://www.cnblogs.com/beliefbetrayal/archive/2012/02/03/2337522.html

【編輯推薦】

  1. Spring事務配置的五種方式
  2. Spring聲明性事務常見問題分析
  3. Java中Class對象詳解
  4. Java API設計清單
  5. Java遠程方法調用RMI
責任編輯:林師授 來源: 信仰や欺騙的博客
相關推薦

2009-08-24 09:46:40

面向切面編程AOP

2013-09-17 10:37:03

AOPAOP教程理解AOP

2023-11-07 16:00:25

面向切面編程開發

2023-10-20 09:32:25

Java技術

2011-04-26 09:33:04

SpringAOP

2024-05-21 09:55:43

AspectOrientedAOP

2023-11-30 08:00:54

面向對象面向切面

2024-04-10 08:59:39

SpringAOP業務

2010-04-26 08:53:06

面向方面編程.NET

2009-06-22 11:27:59

反向控制原理面向切面編程Spring

2009-06-22 15:10:00

java 編程AOP

2021-10-27 07:15:37

SpringAOP編程(

2013-07-30 09:42:41

實現編程接口編程對象編程

2015-09-07 09:13:31

ios教學

2019-11-29 16:21:22

Spring框架集成

2024-06-11 00:04:00

對象AdvisorAdvice

2021-07-14 14:27:01

AndroidAOPhugo

2025-02-17 09:32:18

2015-10-09 13:54:14

切面編程錯誤處理機制

2022-07-30 23:41:53

面向過程面向對象面向協議編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 韩日一区二区三区 | 精品不卡 | 91精产国品一二三区 | 麻豆changesxxx国产 | 一区二区三区四区视频 | 亚洲激情在线 | 久久国产麻豆 | 亚洲精品国产一区 | 麻豆天堂 | 久久av一区二区三区 | 极品电影院| 干出白浆视频 | 日韩电影免费在线观看中文字幕 | www.国产日本 | 精品av | 日韩精品在线免费观看视频 | 免费观看成人性生生活片 | 久热精品视频 | 7799精品视频天天看 | 欧美久久一级特黄毛片 | 国产精品久久久亚洲 | 日本不卡高字幕在线2019 | 在线观看不卡av | 亚洲精品视频免费 | 亚洲第一视频网 | 夜久久 | 玖玖综合网 | 美女艹b| 亚洲视频一区二区三区 | 在线观看国产wwwa级羞羞视频 | 欧美在线综合 | 色综合成人网 | 羞羞视频免费观看入口 | 五月天国产视频 | 人人鲁人人莫人人爱精品 | 久久国产精品一区二区三区 | 涩涩鲁亚洲精品一区二区 | 日韩欧美三区 | 亚洲精品99 | 亚洲国产精品视频一区 | 久久人人网 |