国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

詳解使用Java原生代理實現(xiàn)AOP實例

2019-11-26 13:17:45
字體:
供稿:網(wǎng)友

一說到AOP,大家一定會想到spring,因為這東西實在是太強大了.但是大家一定要清楚,AOP是一只編程思想,而Spring僅僅是AOP的一種實現(xiàn)罷了.

首先百度下:

在軟件業(yè),AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術。AOP是OOP的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對業(yè)務邏輯的各個部分進行隔離,從而使得業(yè)務邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。

今天呢,咱們就一起用Java原生代理實現(xiàn)簡單的AOP功能.

首先,你得需要了解基本的反射知識,否則可能會感到困惑.

不羅嗦了,直接開始擼碼

首先,咱們先寫一個簡單的接口.名字叫AnimalInterface,用來聲明規(guī)范動物的一些基本方法.

這些方法包括 設置名字,獲取名字,叫聲,屬性(原諒我沒文化,其實就是獲得是陸棲還是水棲或者水陸兩棲)

package proxy.imp;public interface AnimalInterface {  //設置名字  void setName(String name);  //獲取名字  String getName();  //叫聲  void say();  //獲取棲性  void getProperty();}

然后咱們實現(xiàn)這個接口,創(chuàng)建一個名叫小黑的Dog

package proxy;import proxy.imp.AnimalInterface;public class DogImp implements AnimalInterface {  private String name = "小黑";  public DogImp() {  }  @Override  public void setName(String name) {    this.name = name;  }  @Override  public String getName() {    return this.name;  }  @Override  public void say() {    System.out.println("小狗:汪汪汪汪.....");  }  @Override  public void getProperty() {    System.out.println("小狗是陸地動物,但是會游泳哦");  }}

大家一定迫不及待了,怎么實現(xiàn)類似AOP的功能呢….

咱們先創(chuàng)建一個名為AOPHandle的類,讓其實現(xiàn)InvocationHandler接口,不能使用invoke時使用proxy作為反射參數(shù)時,因為代理對象的接口,不同于對象,這種代理機制是面向接口,而不是面向類的,如果使用proxy,會造成無限遞歸.然后就是棧溢出,但是依舊能反射成功一次,這說明代理對象和對象的代理是不一樣的,但是咱們可以通過proxy參數(shù)的proxy.getClass()獲得class對象,然后獲得被代理類的方法和參數(shù),這也為注解注入,特定方法注入,屬性注入提供了一種實現(xiàn)途徑吧,關于這個,咱們后面再說..

package proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class AOPHandle implements InvocationHandler{  //保存對象  private Object o;  public AOPHandle(Object o) {    this.o=o;  }  /**   * 這個方法會自動調(diào)用,Java動態(tài)代理機制   * 會傳入下面是個參數(shù)   * @param Object proxy 代理對象的接口,不同于對象   * @param Method method 被調(diào)用方法   * @param Object[] args 方法參數(shù)   * 不能使用invoke時使用proxy作為反射參數(shù)時,因為代理對象的接口,不同于對象   * 這種代理機制是面向接口,而不是面向類的   **/  @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    //方法返回值    Object ret=null;    //打印方法名稱    System.err.println("執(zhí)行方法:"+method.getName()+"n參數(shù)類型為:");    //打印參數(shù)    for(Class type:method.getParameterTypes())      System.err.println(type.getName());    //打印返回類型    System.err.println("返回數(shù)據(jù)類型:"+method.getReturnType().getName());    //反射調(diào)用方法    ret=method.invoke(o, args);    //聲明結束    System.err.println("方法執(zhí)行結束");    //返回反射調(diào)用方法的返回值    return ret;  }}

動態(tài)代理已經(jīng)搞定..然后就是咱們的AnimalFactory了..咱們繼續(xù)

package proxy;import java.lang.reflect.Proxy;public class AnimalFactory {  /***   * 獲取對象方法   * @param obj   * @return   */  private static Object getAnimalBase(Object obj){    //獲取代理對象    return Proxy.newProxyInstance(obj.getClass().getClassLoader(),        obj.getClass().getInterfaces(), new AOPHandle(obj));  }  /***   * 獲取對象方法   * @param obj   * @return   */  @SuppressWarnings("unchecked")  public static T getAnimal(Object obj){    return (T) getAnimalBase(obj);  }  /***   * 獲取對象方法   * @param className   * @return   */  @SuppressWarnings("unchecked")  public static  T getAnimal(String className){    Object obj=null;    try {      obj= getAnimalBase(Class.forName(className).newInstance());    } catch (Exception e) {      e.printStackTrace();    }    return (T)obj;  }  /***   * 獲取對象方法   * @param clz   * @return   */  @SuppressWarnings("unchecked")  public static  T getAnimal(Class clz){    Object obj=null;    try {      obj= getAnimalBase(clz.newInstance());    } catch (Exception e) {      e.printStackTrace();    }    return (T)obj;  }}

終于到最后了…還差什么呢,大家來這里看看效果吧…

哈哈…小二,上個菜..哦~不對,是個測試類..哈哈////

package proxy;import org.junit.Test;import org.junit.runner.RunWith;import org.junit.runners.BlockJUnit4ClassRunner;import proxy.AnimalFactory;import proxy.imp.AnimalInterface;@RunWith(BlockJUnit4ClassRunner.class)public class AOPTest {  @Test  public void Test1() {    AnimalInterface dog=AnimalFactory.getAnimal(DogImp.class);    dog.say();    System.out.println("我的名字是"+dog.getName());    dog.setName("二狗子");    System.out.println("我的名字是"+dog.getName());  }}

啥?什么,,到了最后說,,這又卵用,這不是坑爹么?就捕獲一個這個玩意,什么用啊…

什么AOP,我怎么一點AOP的影子都沒有看到,怎么切入自定義方法,就一個syso輸入,往這忽悠觀眾來了?…..

好吧,那咱們繼續(xù)…看看如何實現(xiàn)注入自定義方法…

首先增加一個接口,咱們就稱為AOP注入接口吧.取名AOPMethod哈

創(chuàng)建after和before方法,接收Object proxy, Method method, Object[] args參數(shù)

這樣就能做更多的事情叻…比如執(zhí)行方法前,記錄類狀態(tài),寫入log.監(jiān)控xx變量,,,

開啟你的腦洞吧.

package proxy.imp;import java.lang.reflect.Method;public interface AOPMethod{  //實例方法執(zhí)行前執(zhí)行的方法  void after(Object proxy, Method method, Object[] args);  //實例方法執(zhí)行后執(zhí)行的方法  void before(Object proxy, Method method, Object[] args);}

然后修改AOPHandle類,增加AOPMethod屬性.

在修改構造方法,讓在類初始化時獲得AOPMethod實例.

最后修改invoke方法….直接上代碼哈

package proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import proxy.imp.AOPMethod;public class AOPHandle implements InvocationHandler{  //保存對象  private AOPMethod method;  private Object o;  public AOPHandle(Object o,AOPMethod method) {    this.o=o;    this.method=method;  }  /**   * 這個方法會自動調(diào)用,Java動態(tài)代理機制   * 會傳入下面是個參數(shù)   * @param Object proxy 代理對象的接口,不同于對象   * @param Method method 被調(diào)用方法   * @param Object[] args 方法參數(shù)   * 不能使用invoke時使用proxy作為反射參數(shù)時,因為代理對象的接口,不同于對象   * 這種代理機制是面向接口,而不是面向類的   **/  @Override  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    Object ret=null;    //修改的地方在這里哦    this.method.before(proxy, method, args);    ret=method.invoke(o, args);    //修改的地方在這里哦    this.method.after(proxy, method, args);    return ret;  }}

呼呼,大功告成,,看起來一切都么問題,萌萌噠..

趕緊更新下測試類…

package proxy;import java.lang.reflect.Method;import org.junit.runner.RunWith;import org.junit.runners.BlockJUnit4ClassRunner;import proxy.imp.AOPMethod;import proxy.imp.AnimalInterface;@RunWith(BlockJUnit4ClassRunner.class)public class AOPTest {  public static void main(String[] args) {    AnimalInterface dog = AnimalFactory.getAnimal(DogImp.class, new AOPMethod() {      // 這里寫方法執(zhí)行前的AOP切入方法      public void before(Object proxy, Method method, Object[] args) {        System.err.println("我在" + method.getName() + "方法執(zhí)行前執(zhí)行");      }      // 這里系方法執(zhí)行后的AOP切入方法      public void after(Object proxy, Method method, Object[] args) {        System.err.println("我在 " + method.getName() + "方法執(zhí)行后執(zhí)行");      }    });    dog.say();    String name1="我的名字是" + dog.getName();    System.out.println(name1);    dog.setName("二狗子");    String name2="我的名字是"+dog.getName();    System.out.println(name2);  }}

呼呼,親們,是不是有注入的感覺了?是不是感覺把自己的方法切進去了???哈哈….

看起來一切都已經(jīng)完美了,但是總覺得差了點什么?哦,對,缺少了類似于Spring那么樣的配置文件..

其實那些已經(jīng)很簡單了,交給你們?nèi)プ霭?設計好XML格式化就妥了,等等,你說什么,還不能攔截自定義方法?

不能像Spring那樣攔截自定義方法?oh~~NO,其實已經(jīng)可以了在before(Object proxy, Method method, Object[] args)中利用method和的給methodName就能做判斷了.

當然,本例的并沒有什么實用意義,更不能個各種完善的AOP框架相比,本文僅僅為您提供一種思路,但是一定要記住,再牛的東西也是一點點積累出來的

實例下載:http://xiazai.VeVB.COm/201701/yuanma/JavaAOP_jb51.rar

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 连城县| 平舆县| 平山县| 光泽县| 双流县| 青浦区| 云和县| 宜兰市| 遵义市| 渭南市| 湘阴县| 南安市| 台前县| 泉州市| 永清县| 汽车| 壶关县| 新巴尔虎左旗| 达日县| 乃东县| 明水县| 伊宁县| 鄢陵县| 延长县| 武乡县| 张家港市| 磐石市| 河池市| 文山县| 麦盖提县| 绥棱县| 科技| 定边县| 溆浦县| 新乡县| 东阿县| 大渡口区| 土默特左旗| 惠水县| 芦溪县| 阿图什市|