最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java代理模式實(shí)例詳解【靜態(tài)代理與動態(tài)代理】

 更新時(shí)間:2019年09月29日 11:47:51   作者:hu_beliefs  
這篇文章主要介紹了Java代理模式,結(jié)合實(shí)例形式詳細(xì)分析了java靜態(tài)代理與動態(tài)代理模式相關(guān)概念、原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了Java代理模式。分享給大家供大家參考,具體如下:

即Proxy Pattern,23種java常用設(shè)計(jì)模式之一。代理模式的定義:對其他對象提供一種代理以控制對這個(gè)對象的訪問。

Java的代理模式是Java中比較常用的設(shè)計(jì)模式,分為2中代理:靜態(tài)代理與動態(tài)代理(JDK動態(tài)代理和cglib動態(tài)代理)

優(yōu)點(diǎn):

  • 職責(zé)清晰 真實(shí)角色只需關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn),非業(yè)務(wù)邏輯部分,后期通過代理類完成即可。
  • 高擴(kuò)展性 不管真實(shí)角色如何變化,由于接口是固定的,代理類無需做任何改動。

缺點(diǎn):

  • 很明顯的一點(diǎn)就是反射機(jī)制,沒有高安全性,性能也相對來講低一些。

代理模式這種設(shè)計(jì)模式是一種使用代理對象來執(zhí)行目標(biāo)對象的方法并在代理對象中增強(qiáng)目標(biāo)對象方法的一種設(shè)計(jì)模式。代理對象代為執(zhí)行目標(biāo)對象的方法,并在此基礎(chǔ)上進(jìn)行相應(yīng)的擴(kuò)展。看起來是有點(diǎn)拗口,首先介紹一個(gè)原則:開閉原則(對擴(kuò)展開放,對修改關(guān)閉)。一種好的設(shè)計(jì)模式甚至是架構(gòu),都是在不修改原有形態(tài)的基礎(chǔ)上擴(kuò)展出新的功能。

事例場景:

小張是一個(gè)普普通通的碼農(nóng),每天勤勤懇懇地碼代碼。某天中午小張剛要去吃飯,一個(gè)電話打到了他的手機(jī)上。“是XX公司的小張嗎?我是YY公司的王AA”?!芭叮峭蹩偘?,有什么事情嗎?”。溝通過后,小張弄明白了,原來客戶有個(gè)需求,剛好負(fù)責(zé)這方面開發(fā)的是小張,客戶就直接找到了他。不過小張卻沒有答應(yīng)客戶的請求,而是讓客戶找產(chǎn)品經(jīng)理小李溝通。

是小張著急去吃面而甩鍋嗎?并不是,只是為了使故事可以套到代理模式上。我們先看一下代理模式的定義: * 為其他對象提供一種代理,以控制對這個(gè)對象的訪問。(Provide a surrogate or placeholder for another object to control access to it)

對照定義,碼農(nóng)小張可以映射為其他對象,產(chǎn)品經(jīng)理小李為小張的代理。我們通過JAVA代碼,表述上面事例。

一、靜態(tài)代理

什么是靜態(tài)代理:靜態(tài)代理就是在程序運(yùn)行前就已經(jīng)確定代理類與代理對象的代理模式

靜態(tài)代理模式就是如上圖所示,構(gòu)造三個(gè)類實(shí)現(xiàn)他們的關(guān)系。

首先會思考的一點(diǎn)就是為什么需要實(shí)現(xiàn)同一個(gè)接口,如果不實(shí)現(xiàn)同一個(gè)接口,一樣可以“代理”功能,所以為什么非要實(shí)現(xiàn)同一個(gè)接口。我個(gè)人認(rèn)為不實(shí)現(xiàn)統(tǒng)一接口的話應(yīng)該叫做聚合而不是代理;然后,實(shí)現(xiàn)統(tǒng)一接口能夠使代理類與被代理類之間的聯(lián)系,提高代碼的復(fù)用性又能解耦。

package staticProxy;
/**
*接口
*/
public interface DAOInterface {
  public void add();
  public void delete();
  public void update();
  public void query();
}
package staticProxy;
/**
*被代理類
*/
public class UserDao implements DAOInterface{
  @Override
  public void add() {
    System.out.println("在目標(biāo)對象中執(zhí)行add");
  }
  @Override
  public void delete() {
    System.out.println("在目標(biāo)對象中執(zhí)行delete");
  }
  @Override
  public void update() {
    System.out.println("在目標(biāo)對象中執(zhí)行update");
  }
  @Override
  public void query() {
    System.out.println("在目標(biāo)對象中執(zhí)行query");
  }
}
package staticProxy;
/**
 * 代理類
 *
 */
public class UserDaoProxy implements DAOInterface{
  UserDao userDao = null;
  public UserDaoProxy(UserDao userDao){
    this.userDao = userDao;
  }
  @Override
  public void add() {
    userDao.add();
    System.out.println("記錄日志add");
  }
  @Override
  public void delete() {
    userDao.delete();
    System.out.println("記錄日志delete");
  }
  @Override
  public void update() {
    userDao.update();
    System.out.println("記錄日志update");
  }
  @Override
  public void query() {
    userDao.query();
    System.out.println("記錄日志query");
  }
}

靜態(tài)代理就是寫死了在代理對象中執(zhí)行這個(gè)方法前后執(zhí)行添加功能的形式,每次要在接口中添加一個(gè)新方法,則需要在目標(biāo)對象中實(shí)現(xiàn)這個(gè)方法,并且在代理對象中實(shí)現(xiàn)相應(yīng)的代理方法;利用Java的反射機(jī)制,動態(tài)的調(diào)用生成代理對象,就能完成動態(tài)代理的需求。

二、動態(tài)代理

1、JDK動態(tài)代理

在代理類管理器的新建代理實(shí)例方法中,必須要獲得類的加載器、類所實(shí)現(xiàn)的接口、還有一個(gè)攔截方法的句柄。

在句柄的invoke中如果不調(diào)用method.invoke則方法不會執(zhí)行。在invoke前后添加通知,就是對原有類進(jìn)行功能擴(kuò)展了。創(chuàng)建好代理對象之后,proxy可以調(diào)用接口中定義的所有方法,因?yàn)樗鼈儗?shí)現(xiàn)了同一個(gè)接口,并且接口的方法實(shí)現(xiàn)類的加載器已經(jīng)被反射框架獲取到了。

package JDKAgency;
/**
 * DAO接口
 */
public interface DAO {
  void add();
  void update();
  void delete();
  void query();
}

package JDKAgency;
/**
 * DAO的實(shí)現(xiàn)類
 */
public class DAOImpl implements DAO {
  @Override
  public void add() {
    System.out.println("添加的方法");
  }
  @Override
  public void update() {
    System.out.println("更新的方法");
  }
  @Override
  public void delete() {
    System.out.println("刪除的方法");
  }
  @Override
  public void query() {
    System.out.println("查詢的方法");
  }
}

package JDKAgency;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 代理類管理器
 */
public class ProxyManager implements InvocationHandler {//動態(tài)代理的核心處理器接口
  private Object object;
  public ProxyManager(Object object) {
    this.object = object;
  }
  public Object createNewInstance() {
    Object o = Proxy.newProxyInstance(object.getClass().getClassLoader(),//真實(shí)對象的類加載器
        object.getClass().getInterfaces(),//真實(shí)對象的所有接口
        this);//代理對象
    return o;
  }
  @Override        //代理對象   執(zhí)行業(yè)務(wù)的方法   參數(shù)
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("before......權(quán)限檢測");//前置通知
    Object invoke = method.invoke(object, args);//動態(tài)調(diào)用執(zhí)行方法
    System.out.println("after......日志監(jiān)控");//后置通知
    return invoke;
  }
}

package JDKAgency;
/**
 * 測試
 */
public class JTest {
  public static void main(String[] args) {
    //創(chuàng)建真實(shí)對象
    DAO dao = new DAOImpl();
    DAO o =(DAO) manager.createNewInstance();
//JDK動態(tài)代理是代理的接口,因此強(qiáng)制轉(zhuǎn)換應(yīng)該轉(zhuǎn)換為接口,而不是實(shí)現(xiàn)類,若強(qiáng)制轉(zhuǎn)換實(shí)現(xiàn)類就會拋出ClassCastException,好比ArrayList與LinkedList實(shí)現(xiàn)統(tǒng)一接口List,兩者也不能相互轉(zhuǎn)換,但都可以向上轉(zhuǎn)型。
    o.add();
    o.query();
  }
}

注意:JDK動態(tài)代理是代理的接口,因此強(qiáng)制轉(zhuǎn)換應(yīng)該轉(zhuǎn)換為接口,而不是實(shí)現(xiàn)類,若強(qiáng)制轉(zhuǎn)換實(shí)現(xiàn)類就會拋出ClassCastException,好比ArrayList與LinkedList實(shí)現(xiàn)統(tǒng)一接口List,兩者也不能相互轉(zhuǎn)換,但都可以向上轉(zhuǎn)型。

補(bǔ)充:

JavaJDK動態(tài)代理報(bào)錯(cuò)java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to *。

javaJDK動態(tài)代理是Java原生代理模式。

注意:JDK動態(tài)代理是代理的接口,因此強(qiáng)制轉(zhuǎn)換應(yīng)該轉(zhuǎn)換為接口,而不是實(shí)現(xiàn)類,若強(qiáng)制轉(zhuǎn)換實(shí)現(xiàn)類就會拋出ClassCastException,好比ArrayList與LinkedList實(shí)現(xiàn)統(tǒng)一接口List,兩者也不能相互轉(zhuǎn)換,但都可以向上轉(zhuǎn)型。

正確的轉(zhuǎn)型方案:

//創(chuàng)建處理器對象
ProxyManager manager = new ProxyManager(dao);
//生成動態(tài)代理對象
// DAO o = (DAO) Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), manager);

2、cglib動態(tài)代理

cglib動態(tài)代理是web應(yīng)用框架常用的一種動態(tài)代理方式。cglib是動態(tài)生成被代理類的子類,注意:是子類。

他需要先引入asm與cglib的jar包。如下圖:

接著廢話不多說,看代碼分析:

package CGlibAgency;
/**
 * 被代理類
 */
public class User {
  public void saveUser(){
    System.out.println("保存對象。");
  }
  public void updateUser(){
    System.out.println("修改對象。");
  }
}

package CGlibAgency;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
 * 代理類管理器
 */
public class Interceptor implements MethodInterceptor {//cgLib需要實(shí)現(xiàn)MethodInterceptor接口,cgLib是基于類的,動態(tài)的生成代理類(被代理類的子類)
  private Enhancer enhancer = new Enhancer();//Enhancer是Cglib代理的重要對象
  public Object createProxy(Class superClass){
    enhancer.setSuperclass(superClass);//獲取父類的Class
    enhancer.setCallback(this);//設(shè)置方法的回調(diào),類似于JDK動態(tài)代理中的Proxy與InvocationHandler實(shí)現(xiàn)類的綁定回調(diào)
    return enhancer.create();//返回代理類的對象
  }
  @Override
  public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    System.out.println("'權(quán)限驗(yàn)證'");
    Object aSuper = methodProxy.invokeSuper(o, objects);//通過虛擬的代理對象的代理方法調(diào)用父類的方法,參數(shù)中一個(gè)是父類,一個(gè)是所有的子類對象數(shù)組(??)
    System.out.println("'日志收集'");
    return aSuper;
  }
}

package CGlibAgency;
/**
 * 測試類
 */
public class JTest {
  public static void main(String[] args) {
    Interceptor interceptor = new Interceptor();//創(chuàng)建代理管理對象
    Object proxy = interceptor.createProxy(User.class);//創(chuàng)建一個(gè)代理類
    System.out.println(User.class.getTypeName());//查看代理類的類型
    User user = (User) proxy;//轉(zhuǎn)型,子類自動向上轉(zhuǎn)型
    user.saveUser();
    user.updateUser();
  }
}

總結(jié):

代理模式不僅可以降低模塊兒之間的耦合,還能做到高復(fù)用,簡化代碼等。spring的AOP模塊就是最直觀的代理模式,使用了動態(tài)代理來實(shí)現(xiàn),在spring中的許多模塊中都具有動態(tài)代理的影子。

更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計(jì)入門與進(jìn)階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總

希望本文所述對大家java程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • Java使用HashMap實(shí)現(xiàn)并查集

    Java使用HashMap實(shí)現(xiàn)并查集

    這篇文章主要為大家詳細(xì)介紹了Java使用HashMap實(shí)現(xiàn)并查集,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • Java中Hashtable類與HashMap類的區(qū)別詳解

    Java中Hashtable類與HashMap類的區(qū)別詳解

    Hashtable的應(yīng)用非常廣泛,HashMap是新框架中用來代替Hashtable的類,也就是說建議使用HashMap,不要使用Hashtable??赡苣阌X得Hashtable很好用,為什么不用呢?這里簡單分析他們的區(qū)別。
    2016-01-01
  • java?Collection集合接口的介紹和使用詳解

    java?Collection集合接口的介紹和使用詳解

    這篇文章主要為大家介紹了java?Collection集合接口的介紹和使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • 處理Log4j2不能打印行號的問題(AsyncLogger)

    處理Log4j2不能打印行號的問題(AsyncLogger)

    這篇文章主要介紹了處理Log4j2不能打印行號的問題(AsyncLogger),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • MyBatis的五種批量插入詳解

    MyBatis的五種批量插入詳解

    這篇文章主要介紹了MyBatis的五種批量插入詳解,MyBatis是一款半自動的ORM持久層框架,具有較高的SQL靈活性,支持高級映射(一對一,一對多),動態(tài)SQL,延遲加載和緩存等特性,但它的數(shù)據(jù)庫無關(guān)性較低,需要的朋友可以參考下
    2023-08-08
  • MyBatisPlus-QueryWrapper多條件查詢及修改方式

    MyBatisPlus-QueryWrapper多條件查詢及修改方式

    這篇文章主要介紹了MyBatisPlus-QueryWrapper多條件查詢及修改方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • java 對數(shù)和指數(shù)計(jì)算方式

    java 對數(shù)和指數(shù)計(jì)算方式

    這篇文章主要介紹了java 對數(shù)和指數(shù)計(jì)算方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java基于JDBC實(shí)現(xiàn)事務(wù),銀行轉(zhuǎn)賬及貨物進(jìn)出庫功能示例

    Java基于JDBC實(shí)現(xiàn)事務(wù),銀行轉(zhuǎn)賬及貨物進(jìn)出庫功能示例

    這篇文章主要介紹了Java基于JDBC實(shí)現(xiàn)事務(wù),銀行轉(zhuǎn)賬及貨物進(jìn)出庫功能,較為詳細(xì)的分析了事務(wù)操作的原理、實(shí)現(xiàn)方法及java基于jdbc連接數(shù)據(jù)庫實(shí)現(xiàn)銀行事務(wù)操作的相關(guān)技巧,需要的朋友可以參考下
    2017-12-12
  • Shiro中session超時(shí)頁面跳轉(zhuǎn)的處理方式

    Shiro中session超時(shí)頁面跳轉(zhuǎn)的處理方式

    這篇文章主要介紹了Shiro中session超時(shí)頁面跳轉(zhuǎn)的處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 一文詳解Java攔截器與過濾器的使用

    一文詳解Java攔截器與過濾器的使用

    這篇文章主要為大家詳細(xì)介紹了Java中攔截器與過濾器的使用與區(qū)別,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)有一定參考價(jià)值,需要的可以參考一下
    2022-04-04

最新評論

巴中市| 宝清县| 措美县| 缙云县| 石狮市| 温宿县| 庆云县| 揭东县| 周口市| 育儿| 突泉县| 杨浦区| 女性| 玉环县| 文昌市| 遂溪县| 阿勒泰市| 丰县| 分宜县| 古丈县| 青河县| 闽侯县| 东乡县| 百色市| 上饶县| 司法| 林周县| 万州区| 讷河市| 洪湖市| 志丹县| 舒城县| 祁连县| 淮安市| 探索| 浮山县| 尉犁县| 嘉禾县| 伊金霍洛旗| 吴忠市| 金溪县|