JDK動態代理和CGLIB代理

JDK代理

參考

https://www.cnblogs.com/MOBIN/p/5597215.html


JDK動態代理和CGLIB代理

通過實現接口實現

通過動態代理,給普通的對象生成代理對象,對其中的方法進行前置和後置的處理

例如spring的事務


使用動態代理的五大步驟

1.通過實現InvocationHandler接口來自定義自己的InvocationHandler;

2.通過Proxy.getProxyClass獲得動態代理類

3.通過反射機制獲得代理類的構造方法,方法簽名為getConstructor(InvocationHandler.class)

4.通過構造函數獲得代理對象並將自定義的InvocationHandler實例對象傳為參數傳入

5.通過代理對象調用目標方法


//接口
public interface MyBuyInterface {
void buy(String goods);
}
//實現這這個接口,也就是後面需要代理的對象
public class MyBuyClass implements MyBuyInterface {
@Override
public void buy(String goods) {

System.out.println("我買了 " + goods);
}
}
//實現自己的InvocationHandler
//實現InvocationHander接口
public class MyInvocationHandler implements InvocationHandler{
//需要被代理的對象
private Object target;
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置處理
System.out.println(new Date());
//這裡是實際調用實際的方法
Object res = method.invoke(target, args);
//後置處理
System.out.println("買完了");
return res;
}
}
//進行實際的調用
public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//方法一
//獲取代理類
Class> proxyClass = Proxy.getProxyClass(MyBuyInterface.class.getClassLoader(), MyBuyInterface.class);
//獲取代理類的構造方法,傳入InvocationHandler接口
Constructor> constructor = proxyClass.getConstructor(InvocationHandler.class);
//通過構造方法創建代理對象,傳入自定義invocationHandler
MyBuyInterface obj = (MyBuyInterface) constructor.newInstance(new MyInvocationHandler(new MyBuyClass()));
//調用方法,此時會調用自定義invocationHandler的invoke方法
obj.buy("蘋果");
//方法二
//上面的幾步可以通過下面這個方法合併為一步
MyBuyInterface oobbjj = (MyBuyInterface) Proxy.newProxyInstance(MyBuyInterface.class.getClassLoader(), new Class[] {MyBuyInterface.class}, new MyInvocationHandler(new MyBuyClass()));

oobbjj.buy("梨子");
}
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
37
38
39
40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
56
57
58
59

運行結果

Tue Aug 28 12:15:37 CST 2018
我買了 蘋果
買完了
Tue Aug 28 12:15:37 CST 2018
我買了 梨子
買完了
1
2
3
4
5
6
7

CGLIB代理

CGLIB會讓生成的代理類繼承被代理類,並在代理類中對代理方法進行強化處理(前置處理、後置處理等)。在CGLIB底層,其實是藉助了ASM這個非常強大的Java字節碼生成框架。

//自定義方法攔截器,實現MethodInterceptor 接口 

public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
System.out.println(new Date());
Object res = proxy.invokeSuper(obj, arg);
System.out.println("買完了");
return res;
}
}
//進行調用
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
//設置父類
enhancer.setSuperclass(MyBuyClass.class);
//設置方法攔截器
enhancer.setCallback(new MyMethodInterceptor());
//生成代理類
MyBuyClass myBuyClass = (MyBuyClass)enhancer.create();
myBuyClass.buy("梨子");
}
//運行結果
Tue Aug 28 13:37:38 CST 2018
我買了 梨子
買完了
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

代理類將委託類作為自己的父類併為其中的非final委託方法創建兩個方法,一個是與委託方法簽名相同的方法,它在方法中會通過super調用委託方法;另一個是代理類獨有的方法。在代理方法中,它會判斷是否存在實現了MethodInterceptor接口的對象,若存在則將調用intercept方法對委託方法進行代理


分享到:


相關文章: