什么是代理模式?
代理模式:在調用處不直接調用目標類進行操作,而是調用代理類,然后通過代理類來調用目標類進行操作。在代理類調用目標類的前后可以添加一些預處理和后處理操作來完成一些不屬于目標類的功能。
為什么要使用代理模式?
通過代理模式可以實現對目標類調用的控制、在目標類調用前/后進行一些不屬于目標類的操作,如:數據驗證、預處理、后處理、異常處理等
什么是靜態代理什么是動態代理?
- 靜態代理:代理類只能實現對”特定接口的實現類“進行代理
- 動態代理:代理類可以實現對多種類的代理
jdk代理和cglib代理區別在哪里?
- jdk動態代理:代理所有“實現的有接口”的目標類
- cglib動態代理:代理任意一個目標類,但對final類和方法無法代理
不同點:jdk動態代理的目標類必須實現的有接口,因為在調用Proxy.newProxyInstance()的時候需要傳入目標類的接口類。而cglib不做此限制。
下面看代碼分析:
定義一個Person接口
1
2
3
4
5
6
|
package com.zpj.designMode.proxy; //定義一個Person接口 public interface Person { public void doWork(); } |
添加一個實現類:MrLi
1
2
3
4
5
6
7
8
9
10
11
|
package com.zpj.designMode.proxy; //添加一個實現類 public class MrLi implements Person { @Override public void doWork() { System.out.println( "-----doWork" ); } } |
靜態代理:
添加一個靜態代理類Proxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package com.zpj.designMode.proxy; //靜態代理,代理必須和目標類實現共同的接口 public class Proxy implements Person { private Person person; // 被代理人 //這里的目標類型決定了該代理類只能代理實現了Person接口的實例,而不能接收其他類型參數,這也就是靜態代理的局限性 public Proxy(Person person) { this .person = person; } @Override public void doWork() { System.out.println( "doSomething-----start" ); person.doWork(); System.out.println( "doSomething-----end" ); } } |
靜態代理測試程序:
1
2
3
4
5
6
7
8
9
10
|
package com.zpj.designMode.proxy; public class Run { public static void main(String[] args) { MrLi li = new MrLi(); Proxy proxy = new Proxy(li); //調用處直接調用代理進行目標方法的操作。 proxy.doWork(); } } |
JDK動態代理:
添加一個代理JDKProxy,該代理實現InvocationHandler接口且覆寫invoke方法。
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
30
31
32
33
|
package com.zpj.designMode.proxy.jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /*** @author Perkins Zhu @date 2017年3月13日 上午8:41:10 */ public class JDKProxy implements InvocationHandler { private Object person; // 被代理人 //這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理。但是要注意下面的newProxyInstance()中的參數 public Object getInstance(Object person) { this .person = person; //與cglib的區別在于這里構建代理對象的時候需要傳入被代理對象的接口對象,第二個參數。而cglib不需要被代理對象實現任何接口即可 return Proxy.newProxyInstance(person.getClass().getClassLoader(), person.getClass().getInterfaces(), this ); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "doSomething---------start" ); method.invoke(person, args); System.out.println( "doSomething---------end" ); return null ; } } |
JDK動態代理測試程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package com.zpj.designMode.proxy.jdk; import com.zpj.designMode.proxy.MrLi; import com.zpj.designMode.proxy.Person; /*** * @author Perkins Zhu * @date 2017年3月13日 上午8:51:31 */ public class Run { public static void main(String[] args) { Person person = (Person) new JDKProxy().getInstance( new MrLi()); //注意這里的person不是目標類person,而是代理類person:debug的時候顯示null,有'$'標識符 person.doWork(); } } |
Cglib動態代理:
添加一個CglibProxy代理,同時實現MethodInterceptor接口。
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
30
31
32
33
34
35
36
|
package com.zpj.designMode.proxy.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; /*** * @author Perkins Zhu * @date 2017年3月13日 上午9:02:54 */ public class CglibProxy implements MethodInterceptor { private Object targetObject; // 這里的目標類型為Object,則可以接受任意一種參數作為被代理類,實現了動態代理 public Object getInstance(Object target) { this .targetObject = target; Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback( this ); //注意該處代理的創建過程 Object proxyObj = enhancer.create(); return proxyObj; // 返回代理對象 } @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { Object obj = null ; System.out.println( "doSomething---------start" ); obj = method.invoke(targetObject, args); System.out.println( "doSomething---------end" ); return obj; } } |
Cglib動態代理測試程序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package com.zpj.designMode.proxy.cglib; import com.zpj.designMode.proxy.MrLi; import com.zpj.designMode.proxy.Person; /*** @author Perkins Zhu @date 2017年3月13日 上午9:07:38 */ public class Run { public static void main(String[] args) { Person person = (Person) new CglibProxy().getInstance( new MrLi()); person.doWork(); } } |
仔細對比Proxy、CglibProxy和JDKProxy區分靜態代理、JDK動態代理和Cglib動態代理的異同點!
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:http://www.cnblogs.com/PerkinsZhu/p/6549211.html