今天呢。我們來學(xué)習(xí)意向JDK的動(dòng)態(tài)代理
也可以使用JDK的API實(shí)現(xiàn)動(dòng)態(tài)代理。這種方式要求目標(biāo)類有一個(gè)接口。這種方式也叫做JDK代理或接口代理。
1、代理類
使用前面靜態(tài)代理一節(jié)的 UserService 和 UserServiceImpl
2、創(chuàng)建代理工廠
package com.qfedu.proxy.utils;
public class ProxyFactoryJDK {
/**
* 目標(biāo)對(duì)象
*/
private Object target;
public ProxyFactoryJDK(Object target) {
this.target = target;
}
//給目標(biāo)對(duì)象生成代理對(duì)象
public Object getProxyInstance() {
return Proxy.newProxyInstance(
target.getClass().getClassLoader(),//指定當(dāng)前目標(biāo)對(duì)象使用類加載器
target.getClass().getInterfaces(),//目標(biāo)對(duì)象的接口類型
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置通知。。。。。。");
//執(zhí)行目標(biāo)對(duì)象方法
Object returnValue = method.invoke(target, args);
System.out.println("后置通知。。。。。。");
return returnValue;
}
}
);
}
}
JDK實(shí)現(xiàn)代理只需要使用newProxyInstance方法,此方法需要三個(gè)參數(shù)
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
這個(gè)方法是靜態(tài)方法,參數(shù)分別為:
ClassLoader loader 指定當(dāng)前目標(biāo)對(duì)象使用類加載器
Class<?>[] interfaces 目標(biāo)對(duì)象實(shí)現(xiàn)的接口的類型
InvocationHandler h 事件處理器,執(zhí)行目標(biāo)對(duì)象的方法時(shí),會(huì)觸發(fā)事件處理器的方法,會(huì)把當(dāng)前執(zhí)行目標(biāo)對(duì)象的方法作為參數(shù)傳入
3、測(cè)試
/**
- 測(cè)試JDK動(dòng)態(tài)代理
*/
@Test
public void test03(){
//創(chuàng)建目標(biāo)對(duì)象
UserService userService = new UserServiceImpl();
//創(chuàng)建代理工廠
ProxyFactoryJDK proxyFactory = new ProxyFactoryJDK(userService);
//從代理工廠或得動(dòng)態(tài)代理類
UserService userService1Proxy = (UserService)proxyFactory.getProxyInstance();
//調(diào)用代理的代理方法
userService1Proxy.save();
}
總結(jié):
如果目標(biāo)對(duì)象有接口,用JDK代理
如果目標(biāo)對(duì)象沒有接口,用Cglib代理