動態代理
動態代理與靜態代理相比沒有過多的代理類,不需要每個業務都單獨創建一個代理類,所有的代理方法都交給一個處理器來處理。
常見的動態代理有兩種:jdk動態代理和cglib動態代理
jdk動態代理
JDK動態代理是基於Java的反射機制實現的,只能對實現了接口的類生成代理,而不能針對類。
IRentingHouse :
/**
* 接口:租房
* jdk動態代理/cglib動態代理
*/
public interface IRentingHouse {
void rentHosue();
}
RentingHouseImpl :
/**
* 委託方(委託對象)
*/
public class RentingHouseImpl implements IRentingHouse {
@Override
public void rentHosue() {
System.out.println("我要租用一室一廳的房子");
}
}
ProxyFactory :
/**
* 代理對象工廠:生成代理對象的
*/
public class ProxyFactory {
private ProxyFactory(){
}
private static ProxyFactory proxyFactory = new ProxyFactory();
public static ProxyFactory getInstance() {
return proxyFactory;
}
/**
* Jdk動態代理
* @param obj 委託對象
* @return 代理對象
*/
public Object getJdkProxy(Object obj) {
// 獲取代理對象
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
// 寫增強邏輯
System.out.println("中介(代理)收取服務費3000元");
// 調用原有業務邏輯
result = method.invoke(obj,args);
System.out.println("客戶信息賣了3毛錢");
return result;
}
});
}
}
jdk動態代理就是調用Proxy.newProxyInstance()方法,第一個參數爲類加載器,第二個參數爲委託對象實現的接口,第三個參數爲增強的邏輯,即InvocationHandler接口的具體實現,invoke()方法中的邏輯就是增強邏輯。
proxy:代理對象本事,method:調用的方法,args:調用的方法的參數。
測試類JdkProxy :
public class JdkProxy {
public static void main(String[] args) {
IRentingHouse rentingHouse = new RentingHouseImpl(); // 委託對象---委託方
// 從代理對象工廠獲取代理對象
IRentingHouse jdkProxy = (IRentingHouse) ProxyFactory.getInstance().getJdkProxy(rentingHouse);
jdkProxy.rentHosue();
}
}
測試結果:
cglib動態代理
Cglib採用了底層的字節碼技術,針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法,並覆蓋其中方法實現增強,但是因爲採用的是繼承,所以該類或方法最好不要聲明成final, 對於final類或方法,是無法繼承的。
ProxyFactory :
/**
*
* 代理對象工廠:生成代理對象的
*/
public class ProxyFactory {
private ProxyFactory(){
}
private static ProxyFactory proxyFactory = new ProxyFactory();
public static ProxyFactory getInstance() {
return proxyFactory;
}
/**
* 使用cglib動態代理生成代理對象
* @param obj 委託對象
* @return
*/
public Object getCglibProxy(Object obj) {
return Enhancer.create(obj.getClass(), new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object result = null;
System.out.println("中介(代理)收取服務費3000元");
result = method.invoke(obj,objects);
System.out.println("客戶信息賣了3毛錢");
return result;
}
});
}
}
cglib動態代理就是調用 Enhancer.create()方法。第一個參數爲委託對象的class,第二個參數爲增強的業務邏輯,即實現MethodInterceptor接口中的intercept()方法,
o:代理對象的引用,method:調用的方法,objects:調用的方法的參數,MethodProxy :對當前執行的方法代理對象的封裝
測試類CglibProxy :
public class CglibProxy {
public static void main(String[] args) {
RentingHouseImpl rentingHouse = new RentingHouseImpl(); // 委託對象
// 獲取rentingHouse對象的代理對象,
// Enhancer類似於JDK動態代理中的Proxy
// 通過實現接口MethodInterceptor能夠對各個方法進行攔截增強,類似於JDK動態代理中的InvocationHandler
// 使用工廠來獲取代理對象
RentingHouseImpl cglibProxy = (RentingHouseImpl) ProxyFactory.getInstance().getCglibProxy(rentingHouse);
cglibProxy.rentHosue();
}
}
測試結果: