一些Java項(xiàng)目中在mybatis與spring整合中有MapperScannerConfigurer的使用,該類(lèi)通過(guò)反向代理自動(dòng)生成基于接口的動(dòng)態(tài)代理類(lèi)。
有鑒于此,本文淺析了java的動(dòng)態(tài)代理。
本文使用動(dòng)態(tài)代理模擬處理事務(wù)的攔截器。
接口:
1
2
3
4
5
|
public interface UserService { public void addUser(); public void removeUser(); public void searchUser(); } |
實(shí)現(xiàn)類(lèi):
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動(dòng)態(tài)代理的實(shí)現(xiàn)有2種方式
1.jdk自帶的動(dòng)態(tài)代理
使用jdk自帶的動(dòng)態(tài)代理需要了解InvocationHandler接口和Proxy類(lèi),他們都是在java.lang.reflect包下。
InvocationHandler介紹:
InvocationHandler是代理實(shí)例的調(diào)用處理程序?qū)崿F(xiàn)的接口。
每個(gè)代理實(shí)例都具有一個(gè)關(guān)聯(lián)的InvocationHandler。對(duì)代理實(shí)例調(diào)用方法時(shí),這個(gè)方法會(huì)調(diào)用InvocationHandler的invoke方法。
Proxy介紹:
Proxy 提供靜態(tài)方法用于創(chuàng)建動(dòng)態(tài)代理類(lèi)和實(shí)例。
實(shí)例(模擬AOP處理事務(wù)):
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 ; } } |
測(cè)試代碼:
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(); } } |
測(cè)試結(jié)果:
1
2
3
|
start Transaction add user end Transaction |
很明顯,我們通過(guò)userServiceProxy這個(gè)代理類(lèi)進(jìn)行方法調(diào)用的時(shí)候,會(huì)在方法調(diào)用前后進(jìn)行事務(wù)的開(kāi)啟和關(guān)閉。
2. 第三方庫(kù)cglib
CGLIB是一個(gè)功能強(qiáng)大的,高性能、高質(zhì)量的代碼生成庫(kù),用于在運(yùn)行期擴(kuò)展Java類(lèi)和實(shí)現(xiàn)Java接口。
它與JDK的動(dòng)態(tài)代理的之間最大的區(qū)別就是:
JDK動(dòng)態(tài)代理是針對(duì)接口的,而cglib是針對(duì)類(lèi)來(lái)實(shí)現(xiàn)代理的,cglib的原理是對(duì)指定的目標(biāo)類(lèi)生成一個(gè)子類(lèi),并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),但因?yàn)椴捎玫氖抢^承,所以不能對(duì)final修飾的類(lèi)進(jìn)行代理。
實(shí)例代碼如下:
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 ; } } |
測(cè)試代碼:
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(); } } |
測(cè)試結(jié)果:
1
2
3
|
start Transaction by cglib add user end Transaction by cglib |
感興趣的讀者可以實(shí)際測(cè)試一下本文實(shí)例,相信會(huì)有很大的收獲。