一、代理
在使用動態(tài)代理實現(xiàn)攔截器之前我們先簡單了解一下什么Java的代理。
代理,顧名思義,就是不直接操作被代理(下面都用目標(biāo)對象稱呼,聽起來舒服一些)對象,而是通過一個代理對象去間接的使用目標(biāo)對象中的方法。代理分為兩種模式,一種是靜態(tài)代理,一種是動態(tài)代理。接下來先寫一個靜態(tài)代理的例子。
無論是靜態(tài)代理還是動態(tài)代理,目標(biāo)對象(target)都要實現(xiàn)一個接口(interface),注意,如果使用cglib提供的代理,則不必實現(xiàn)接口,而是通過子類去實現(xiàn),暫不討論該種方式。
(1)先定義一個接口
1
2
3
|
public interface IUserDao { void save(); } |
(2)定義目標(biāo)對象(target)
1
2
3
4
5
|
public class UserDaoImpl implements IUserDao { public void save() { System.out.println( "--------已經(jīng)保存數(shù)據(jù)---------" ); } } |
(3)定義代理對象
1
2
3
4
5
6
7
8
9
10
11
|
public class UserDaoProxy implements IUserDao { private IUserDao target; //將目標(biāo)對象放到代理對象中 public UserDaoProxy(IUserDao target){ this .target = target; } public void save() { System.out.println( "------開始事務(wù)------" ); target.save(); System.out.println( "-------提交事務(wù)------" ); } } |
測試一下:
1
2
3
4
5
6
7
|
public class Test { public static void main(String[] args){ IUserDao userDao = new UserDaoImpl(); UserDaoProxy proxy = new UserDaoProxy(userDao); proxy.save(); //通過代理對象調(diào)用save方法 } } |
輸出結(jié)果為:
------開始事務(wù)------
--------已經(jīng)保存數(shù)據(jù)----------------提交事務(wù)------
這種方式有一個問題,就是代理對象必須也要實現(xiàn)被代理對象所實現(xiàn)的同一個接口,這就出現(xiàn)了嚴(yán)重的耦合。所以,下面使用一種改進(jìn)的方式,即動態(tài)代理(jdk代理)。
動態(tài)代理方式也需要目標(biāo)對象(target)實現(xiàn)一個接口
(1)定義一個接口(IUserDao)
(2)定義一個目標(biāo)對象類(UserDaoImpl)
(3)創(chuàng)建動態(tài)代理類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class ProxyFactory { //維護(hù)一個目標(biāo)對象 private Object target; public ProxyFactory(Object target) { this .target = target; } //給目標(biāo)對象生成代理對象 public Object getProxyInstance() { System.out.println( "----target class---" + target.getClass()); System.out.println( "----target interfaces---" + target.getClass().getInterfaces()); return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "----開始事務(wù)2-----" ); //執(zhí)行目標(biāo)對象方法 Object returnValue = method.invoke(target, args); System.out.println( "----提交事務(wù)2----" ); return returnValue; } }); } } |
測試一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class Test { public static void main(String[] args) { //目標(biāo)對象 IUserDao target = new UserDao(); System.out.println(target.getClass()); //給目標(biāo)對象創(chuàng)建代理對象 IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance(); System.out.println( "----proxy----:" + proxy.getClass()); proxy.save(); proxy.delete(); } } |
輸出結(jié)果:
class com.jd.pattern.proxy.dynamicProxy.UserDao
----target class---class com.jd.pattern.proxy.dynamicProxy.UserDao
----target interfaces---[Ljava.lang.Class;@1fb3ebeb
----proxy----:class com.sun.proxy.$Proxy0
----開始事務(wù)2-----
-----保存完成------
----提交事務(wù)2----
----開始事務(wù)2-----
----刪除完成--------提交事務(wù)2----
二、使用動態(tài)代理實現(xiàn)一個簡單的攔截器
既然是采用動態(tài)代理的方式,那么肯定會有 接口、目標(biāo)類、代理類,再加一個攔截器
1、定義一個接口
1
2
3
|
public interface BusinessFacade { void doSomething(); } |
2、定義一個目標(biāo)對象
1
2
3
4
5
|
public class BusinessClass implements BusinessFacade { public void doSomething() { System.out.println( "在業(yè)務(wù)組件BusinessClass中調(diào)用doSomething方法" ); } } |
3、創(chuàng)建攔截器
1
2
3
4
5
6
7
8
9
|
public class InterceptorClass { public void before() { System.out.println( "在InterceptorClass中調(diào)用方法:before()" ); } public void after() { System.out.println( "在InterceptorClass中調(diào)用方法:after()" ); } } |
4、創(chuàng)建代理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class DynamicProxyHandler { //聲明被代理對象 private Object target; //創(chuàng)建攔截器 InterceptorClass interceptor = new InterceptorClass(); //動態(tài)生成一個代理對象,并綁定被代理類和代理處理器 public Object getProxyInstance( final Object target) { this .target = target; return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { interceptor.before(); Object result = method.invoke(target, args); interceptor.after(); return result; } }); } } |
測試一下:
1
2
3
4
5
6
7
8
9
10
11
12
|
public class Test { public static void main(String[] args) { //創(chuàng)建動態(tài)代理工具 DynamicProxyHandler proxyHandler = new DynamicProxyHandler(); //創(chuàng)建業(yè)務(wù)組件 BusinessFacade target = new BusinessClass(); //獲取代理對象 BusinessFacade proxy = (BusinessFacade) proxyHandler.getProxyInstance(target); //通過代理對象調(diào)用目標(biāo)對象方法 proxy.doSomething(); } } |
輸出結(jié)果:
在InterceptorClass中調(diào)用方法:before()
在業(yè)務(wù)組件BusinessClass中調(diào)用doSomething方法
在InterceptorClass中調(diào)用方法:after()
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/zjl_pcw/article/details/80505114