一些Java項目中在mybatis與spring整合中有MapperScannerConfigurer的使用,該類通過反向代理自動生成基于接口的動態代理類。
有鑒于此,本文淺析了java的動態代理。
本文使用動態代理模擬處理事務的攔截器。
接口:
1
2
3
4
5
|
public interface UserService { public void addUser(); public void removeUser(); public void searchUser(); } |
實現類:
1
2
3
4
5
6
7
8
9
10
11
|
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處理事務):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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 ; } } |
測試代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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(); } } |
測試結果:
1
2
3
|
start Transaction add user end Transaction |
很明顯,我們通過userServiceProxy這個代理類進行方法調用的時候,會在方法調用前后進行事務的開啟和關閉。
2. 第三方庫cglib
CGLIB是一個功能強大的,高性能、高質量的代碼生成庫,用于在運行期擴展Java類和實現Java接口。
它與JDK的動態代理的之間最大的區別就是:
JDK動態代理是針對接口的,而cglib是針對類來實現代理的,cglib的原理是對指定的目標類生成一個子類,并覆蓋其中方法實現增強,但因為采用的是繼承,所以不能對final修飾的類進行代理。
實例代碼如下:
1
2
3
4
5
6
7
8
9
10
11
|
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 ; } } |
測試代碼:
1
2
3
4
5
6
7
8
9
10
11
12
|
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(); } } |
測試結果:
1
2
3
|
start Transaction by cglib add user end Transaction by cglib |
感興趣的讀者可以實際測試一下本文實例,相信會有很大的收獲。