一些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
感興趣的讀者可以實際測試一下本文實例,相信會有很大的收獲。