程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> java實現動態代理方法淺析

java實現動態代理方法淺析

編輯:JAVA編程入門知識

一些Java項目中在mybatis與spring整合中有MapperScannerConfigurer的使用,該類通過反向代理自動生成基於接口的動態代理類。

有鑒於此,本文淺析了java的動態代理。

本文使用動態代理模擬處理事務的攔截器。

接口:

public interface UserService {
  public void addUser();
  public void removeUser();
  public void searchUser();
}

實現類:

public class UserServiceImpl implements UserService {
  public void addUser() {
    System.out.println("add user");
  }
  public void removeUser() {
    System.out.println("remove user");
  }
  public void searchUser() {
    System.out.println("search user");
  }
}

java動態代理的實現有2種方式

1.jdk自帶的動態代理

使用jdk自帶的動態代理需要了解InvocationHandler接口和Proxy類,他們都是在java.lang.reflect包下。

InvocationHandler介紹:

InvocationHandler是代理實例的調用處理程序實現的接口。

每個代理實例都具有一個關聯的InvocationHandler。對代理實例調用方法時,這個方法會調用InvocationHandler的invoke方法。

Proxy介紹:

Proxy 提供靜態方法用於創建動態代理類和實例。

實例(模擬AOP處理事務):

public class TransactionInterceptor implements InvocationHandler {

  private Object target;

  public void setTarget(Object target) {
    this.target = target;
  }
  
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("start Transaction");
    method.invoke(target, args);
    System.out.println("end Transaction");
    return null;
  }

}

測試代碼:

public class TestDynamicProxy {

  @Test
  public void testJDK() {
    TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
    UserService userService = new UserServiceImpl();
    transactionInterceptor.setTarget(userService);
    UserService userServiceProxy =
        (UserService) Proxy.newProxyInstance(
            userService.getClass().getClassLoader(),
            userService.getClass().getInterfaces(),
            transactionInterceptor);
    userServiceProxy.addUser();
  }

}

測試結果:

start Transaction
add user
end Transaction

很明顯,我們通過userServiceProxy這個代理類進行方法調用的時候,會在方法調用前後進行事務的開啟和關閉。

2. 第三方庫cglib

CGLIB是一個功能強大的,高性能、高質量的代碼生成庫,用於在運行期擴展Java類和實現Java接口。

它與JDK的動態代理的之間最大的區別就是:

JDK動態代理是針對接口的,而cglib是針對類來實現代理的,cglib的原理是對指定的目標類生成一個子類,並覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。

實例代碼如下:

public class UserServiceCallBack implements MethodInterceptor {

  @Override
  public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    System.out.println("start Transaction by cglib");
    methodProxy.invokeSuper(o, args);
    System.out.println("end Transaction by cglib");
    return null;
  }

}

測試代碼:

public class TestDynamicProxy {

  @Test
  public void testCGLIB() {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(UserServiceImpl.class);
    enhancer.setCallback(new UserServiceCallBack());
    UserServiceImpl proxy = (UserServiceImpl)enhancer.create();
    proxy.addUser();
  }

}

測試結果:

start Transaction by cglib
add user
end Transaction by cglib

感興趣的讀者可以實際測試一下本文實例,相信會有很大的收獲。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved