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

淺談Java代理(jdk靜態(tài)代理、動態(tài)代理和cglib動態(tài)代理)

 更新時間:2017年01月22日 09:34:33   投稿:jingxian  
下面小編就為大家?guī)硪黄獪\談Java代理(jdk靜態(tài)代理、動態(tài)代理和cglib動態(tài)代理)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

一、代理是Java常用的設(shè)計模式,代理類通過調(diào)用被代理類的相關(guān)方法,并對相關(guān)方法進(jìn)行增強(qiáng)。加入一些非業(yè)務(wù)性代碼,比如事務(wù)、日志、報警發(fā)郵件等操作。

二、jdk靜態(tài)代理

1、業(yè)務(wù)接口

/** 
 * 業(yè)務(wù)接口 
 * @author pc 
 * 
 */
public interface UserService { 
   
  // 增加一個用戶 
  public void addUser(); 
  // 編輯賬戶 
  public void editUser(); 
 
} 

2、業(yè)務(wù)實現(xiàn)類

/** 
 * 業(yè)務(wù)實現(xiàn)類 
 * @author pc 
 * 
 */
public class UserServiceImpl implements UserService { 
 
  public void addUser() { 
    System.out.println("增加一個用戶。。。"); 
  } 
 
  public void editUser() { 
    System.out.println("編輯一個用戶。。。"); 
  } 
 
} 

3、代理類

/**
* 代理類
*
* @author pc
*
*/
public class UserServiceProxy implements UserService {

private UserServiceImpl userImpl;

public UserServiceProxy(UserServiceImpl countImpl) {
this.userImpl = countImpl;
}

public void addUser() {
System.out.println("代理類方法,進(jìn)行了增強(qiáng)。。。");
System.out.println("事務(wù)開始。。。");
// 調(diào)用委托類的方法;
userImpl.addUser();
System.out.println("處理結(jié)束。。。");
}

public void editUser() {
System.out.println("代理類方法,進(jìn)行了增強(qiáng)。。。");
System.out.println("事務(wù)開始。。。");
// 調(diào)用委托類的方法;
userImpl.editUser();
System.out.println("事務(wù)結(jié)束。。。");
}

}
  

4、測試類

public static void main(String[] args) { 
  UserServiceImpl userImpl = new UserServiceImpl(); 
  UserServiceProxy proxy = new UserServiceProxy(userImpl); 
  proxy.addUser(); 
  System.out.println("----------分割線----------"); 
  proxy.editUser(); 
} 

5、結(jié)果

代理類方法,進(jìn)行了增強(qiáng)。。。

事務(wù)開始。。。
增加一個用戶。。。
處理結(jié)束。。。

----------分割線----------

代理類方法,進(jìn)行了增強(qiáng)。。。
事務(wù)開始。。。
編輯一個用戶。。。
事務(wù)結(jié)束。。。
  

三、jdk動態(tài)代理

1、業(yè)務(wù)接口

/** 
 * 業(yè)務(wù)接口 
 * @author pc 
 * 
 */
public interface UserService { 
   
  // 增加一個用戶 
  public void addUser(); 
  // 編輯賬戶 
  public void editUser(); 
 
} 

2、業(yè)務(wù)接口實現(xiàn)類

/** 
 * 業(yè)務(wù)接口實現(xiàn)類 
 * @author pc 
 * 
 */
public class UserServiceImpl implements UserService { 
 
  public void addUser() { 
    System.out.println("增加一個用戶。。。"); 
  } 
 
  public void editUser() { 
    System.out.println("編輯一個用戶。。。"); 
  } 
} 

3、代理類

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 
 
/** 
 * 
 * @author pc 
 * 
 */
public class ServiceInvocationHandler implements InvocationHandler { 
 
  // 目標(biāo)對象 
  private Object target; 
 
  public ServiceInvocationHandler(Object target) { 
    super(); 
    this.target = target; 
  } 
 
  /** 
   * 創(chuàng)建代理實例 
   * @return 
   * @throws Throwable 
   */
  public Object getProxy() throws Throwable { 
    return Proxy.newProxyInstance(Thread.currentThread() 
        .getContextClassLoader(), this.target.getClass() 
        .getInterfaces(), this); 
    // 這樣寫只返回了目標(biāo)對象,沒有生成代理對象。 
    // return target; 
  } 
 
  /** 
   * 實現(xiàn)InvocationHandler接口方法 
   * 執(zhí)行目標(biāo)對象的方法,并進(jìn)行增強(qiáng) 
   */
  public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable { 
    Object result = null; 
    System.out.println("代理類方法,進(jìn)行了增強(qiáng)。。。"); 
    System.out.println("事務(wù)開始。。。"); 
    // 執(zhí)行目標(biāo)方法對象 
    result = method.invoke(target, args); 
    System.out.println("事務(wù)結(jié)束。。。"); 
    return result; 
  } 
 
} 

4、測試類

public class Test { 
  /** 
   * jdk動態(tài)代理會生成一個動態(tài)代理類,生成相應(yīng)的字節(jié)碼,然后通過ClassLoader加載字節(jié)碼。 
   * 該實例繼承了Proxy類,并實現(xiàn)了業(yè)務(wù)接口,在實現(xiàn)的方法里通過反射調(diào)用了InvocationHandler接口實現(xiàn)類 
   * 的invoke()回調(diào)方法。 
   * @param args 
   * @throws Throwable 
   */
  public static void main(String[] args) throws Throwable { 
    UserService userService = new UserServiceImpl(); 
    ServiceInvocationHandler handler = new ServiceInvocationHandler(userService); 
    // 根據(jù)目標(biāo)生成代理對象 
    UserService proxy = (UserService) handler.getProxy(); 
    proxy.addUser(); 
//   proxy.editUser(); 
 
  } 
 
} 

5、測試結(jié)果

代理類方法,進(jìn)行了增強(qiáng)。。。
事務(wù)開始。。。
增加一個用戶。。。
事務(wù)結(jié)束。。。

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

需要引入cglib的jar包,

在pom.xml加入依賴:

<!-- https://mvnrepository.com/artifact/cglib/cglib --> 
<dependency> 
  <groupId>cglib</groupId> 
  <artifactId>cglib</artifactId> 
  <version>2.2.2</version> 
</dependency> 

  

1、業(yè)務(wù)類,沒有實現(xiàn)接口

/** 
 * 業(yè)務(wù)類 
 * 沒有實現(xiàn)接口 
 * 如果類是final的,則沒法生成代理對象,報錯。 
 * 如果方法是final的,代理無效 
 * @author pc 
 * 
 */
public class UserServiceImpl { 
 
  public void addUser() { 
    System.out.println("增加一個用戶。。。"); 
  } 
 
  public void editUser() { 
    System.out.println("編輯一個用戶。。。"); 
  } 
} 

2、代理類

import java.lang.reflect.Method; 
 
import net.sf.cglib.proxy.Enhancer; 
import net.sf.cglib.proxy.MethodInterceptor; 
import net.sf.cglib.proxy.MethodProxy; 
 
/** 
 * 使用Cglib動態(tài)代理 
 * @author pc 
 * 
 */
public class UserServiceCglib implements MethodInterceptor{ 
 
  private Object target; 
   
  /** 
   * 創(chuàng)建代理實例 
   * @param target 
   * @return 
   */
  public Object getInstance(Object target){ 
    this.target = target; 
    Enhancer enhancer = new Enhancer(); 
    enhancer.setSuperclass(this.target.getClass()); 
    // 設(shè)置回調(diào)方法 
    enhancer.setCallback(this); 
    // 創(chuàng)建代理對象 
    return enhancer.create(); 
  } 
   
  /** 
   * 實現(xiàn)MethodInterceptor接口要重寫的方法。 
   * 回調(diào)方法 
   */
  public Object intercept(Object obj, Method method, Object[] args, 
      MethodProxy proxy) throws Throwable { 
    System.out.println("事務(wù)開始。。。");   
    Object result = proxy.invokeSuper(obj, args);   
    System.out.println("事務(wù)結(jié)束。。。");   
    return result;   
  } 
 
} 

3、測試類

public class TestCglib { 
 
  public static void main(String[] args) { 
    UserServiceCglib cglib = new UserServiceCglib(); 
    UserServiceImpl bookFacadeImpl = (UserServiceImpl)cglib.getInstance(new UserServiceImpl()); 
    bookFacadeImpl.addUser(); 
//   bookFacadeImpl.editUser(); 
  } 
} 

4、結(jié)果:

事務(wù)開始。。。
增加一個用戶。。。
事務(wù)結(jié)束。。。

5、如果業(yè)務(wù)實現(xiàn)類被定義成final類,就會報以下錯誤

Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class class cn.xx.xx.cgilb.UserServiceImpl 
  at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446) 
  at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) 
  at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) 
  at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) 
  at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) 
  at cn.pconline.proxy.cgilb.UserServiceCglib.getInstance(UserServiceCglib.java:30) 
  at cn.pconline.proxy.cgilb.TestCglib.main(TestCglib.java:7) 

五、總結(jié)

1、原理

jdk靜態(tài)代理實現(xiàn)比較簡單,一般是直接代理對象直接包裝了被代理對象。

jdk動態(tài)代理是接口代理,被代理類A需要實現(xiàn)業(yè)務(wù)接口,業(yè)務(wù)代理類B需要實現(xiàn)InvocationHandler接口。

jdk動態(tài)代理會根據(jù)被代理對象生成一個繼承了Proxy類,并實現(xiàn)了該業(yè)務(wù)接口的jdk代理類,該類的字節(jié)碼會被傳進(jìn)去的ClassLoader加載,創(chuàng)建了jdk代理對象實例,

jdk代理對象實例在創(chuàng)建時,業(yè)務(wù)代理對象實例會被賦值給Proxy類,jdk代理對象實例也就有了業(yè)務(wù)代理對象實例,同時jdk代理對象實例通過反射根據(jù)被代理類的業(yè)務(wù)方法創(chuàng)建了相應(yīng)的Method對象m(可能有多個)。當(dāng)jdk代理對象實例調(diào)用業(yè)務(wù)方法,如proxy.addUser();這個會先把對應(yīng)的m對象作為參數(shù)傳給invoke()方法(就是invoke方法的第二個參數(shù)),調(diào)用了jdk代理對象實例的invoke()回調(diào)方法,在invoke方法里面再通過反射來調(diào)用被代理對象的因為方法,即result = method.invoke(target, args);。

cglib動態(tài)代理是繼承代理,通過ASM字節(jié)碼框架修改字節(jié)碼生成新的子類,重寫并增強(qiáng)方法的功能。

2、優(yōu)缺點

jdk靜態(tài)代理類只能為一個被代理類服務(wù),如果需要代理的類比較多,那么會產(chǎn)生過多的代理類。jdk靜態(tài)代理在編譯時產(chǎn)生class文件,運(yùn)行時無需產(chǎn)生,可直接使用,效率好。

jdk動態(tài)代理必須實現(xiàn)接口,通過反射來動態(tài)代理方法,消耗系統(tǒng)性能。但是無需產(chǎn)生過多的代理類,避免了重復(fù)代碼的產(chǎn)生,系統(tǒng)更加靈活。

cglib動態(tài)代理無需實現(xiàn)接口,通過生成子類字節(jié)碼來實現(xiàn),比反射快一點,沒有性能問題。但是由于cglib會繼承被代理類,需要重寫被代理方法,所以被代理類不能是final類,被代理方法不能是final。

因此,cglib的應(yīng)用更加廣泛一點。

以上這篇淺談Java代理(jdk靜態(tài)代理、動態(tài)代理和cglib動態(tài)代理)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java多線程從入門到精通看這篇就夠了

    java多線程從入門到精通看這篇就夠了

    熟悉 Java 多線程編程的同學(xué)都知道,當(dāng)我們線程創(chuàng)建過多時,容易引發(fā)內(nèi)存溢出,因此我們就有必要使用線程池的技術(shù)了,今天通過本文給大家分享java多線程從入門到精通的相關(guān)知識,一起看看吧
    2021-06-06
  • Java集合的定義與Collection類使用詳解

    Java集合的定義與Collection類使用詳解

    這篇文章主要介紹了Java集合的定義及Collection工具類使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-11-11
  • java webApp異步上傳圖片實現(xiàn)代碼

    java webApp異步上傳圖片實現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了java webApp異步上傳圖片實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 淺談Mybatis SqlSession執(zhí)行流程

    淺談Mybatis SqlSession執(zhí)行流程

    本文主要介紹了淺談Mybatis SqlSession執(zhí)行流程,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Mybatis SQL日志如何轉(zhuǎn)換為可執(zhí)行sql

    Mybatis SQL日志如何轉(zhuǎn)換為可執(zhí)行sql

    這篇文章主要介紹了Mybatis SQL日志如何轉(zhuǎn)換為可執(zhí)行sql問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Spring中任務(wù)調(diào)度之解讀@Scheduled和@Schedules注解的使用

    Spring中任務(wù)調(diào)度之解讀@Scheduled和@Schedules注解的使用

    這篇文章主要介紹了Spring中任務(wù)調(diào)度之解讀@Scheduled和@Schedules注解的使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • MyBatis 動態(tài)拼接Sql字符串的問題

    MyBatis 動態(tài)拼接Sql字符串的問題

    MyBatis的動態(tài)SQL,解決了SQL字符串拼接的痛苦。下文分步驟給大家詳細(xì)介紹了MyBatis 動態(tài)拼接Sql字符串的問題,非常不錯,感興趣的朋友一起看下吧
    2016-08-08
  • Java實現(xiàn)LRU緩存算法的參考示例

    Java實現(xiàn)LRU緩存算法的參考示例

    這篇文章主要介紹了JAVA實現(xiàn)LRU緩存算法的參考示例,幫助大家根據(jù)需求實現(xiàn)算法,對大家的學(xué)習(xí)或工作有一定的參考價值,需要的朋友可以參考下
    2023-05-05
  • Kotlin基本類型自動裝箱出現(xiàn)問題解決辦法

    Kotlin基本類型自動裝箱出現(xiàn)問題解決辦法

    這篇文章主要介紹了Kotlin基本類型自動裝箱出現(xiàn)問題解決辦法的相關(guān)資料,希望通過本文能幫助到大家,讓大家遇到這樣的問題順利解決,需要的朋友可以參考下
    2017-10-10
  • 詳解spring中使用Elasticsearch的代碼實現(xiàn)

    詳解spring中使用Elasticsearch的代碼實現(xiàn)

    本篇文章主要介紹了詳解spring中使用Elasticsearch的代碼實現(xiàn),具有一定的參考價值,有興趣的可以了解一下
    2017-05-05

最新評論

莱阳市| 无锡市| 思南县| 高州市| 九龙坡区| 香格里拉县| 武强县| 沧源| 昭觉县| 淮北市| 资源县| 临颍县| 凉山| 蒙阴县| 平顺县| 神农架林区| 桦川县| 东辽县| 利辛县| 吉林省| 庄浪县| 海晏县| 安庆市| 固镇县| 阳城县| 邵武市| 石嘴山市| 武功县| 普兰县| 通城县| 怀柔区| 轮台县| 乐昌市| 海南省| 巴青县| 仪陇县| 康平县| 定安县| 大港区| 南宁市| 益阳市|