動態代理的作用:在不改變源碼的情況下增強方法;
舉個例子,在進行簡單的jdbc操作的時候,你想做到每執行一次sql語句就打印一句話,作爲日誌.
說明:本例子是基於子類(任何一個java普通類)的動態代理,(當然也有基於接口的動態代理模式了)[點擊這裏連接到](https://blog.csdn.net/weixin_45127611/article/details/104523192);
首先定義簡單類,定義一個簡單的功能吧:
public class Producter{
@Override
public Float saleProduct(Float money) {
System.out.println("賣了"+money);
return money;
}
}
好,類出來了,現在給你出個問題,你怎麼能夠在不改變源碼的情況下,讓每次執行這個方法之前打印一行字,或者是改變money參數的倍數等簡單操作??
這些問題用JDK官方提供的 Proxy 類,就沒有辦法解決了,因爲這個java類沒有實現任何的接口,只是一個java的簡單類;但是這也是有辦法增強的,不過要用到三方jar包(cglib和asm)少一不可
接下來是類代碼:
public class TestCglib {
//要代理的對象
private static IProduct target = new ProductImpl();
public TestCglib(IProduct target){
this.target = target;
}
public IProduct getlLoggingProxy(){
IProduct proxy = null;
//代理對象由哪一個類加載器負責加載
Class loader = target.getClass();
//代理對象的類型,即其中有哪些方法
MethodInterceptor met = new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
Object returnValue = null;
if("saleProduct".equals(arg1.getName())) {
Float money = (float) (0.8*(Float)arg2[0]);
returnValue = arg1.invoke(target, money);
}
return returnValue;
}
};
return proxy = (IProduct)Enhancer.create(loader,met);
}
public static void main(String[] args) {
TestCglib tc = new TestCglib(new ProductImpl());
IProduct pr = tc.getlLoggingProxy();
pr.saleProduct(1000f);
/*
IProduct proxy = (IProduct)Enhancer.create(target.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
Object returnValue = null;
if("saleProduct".equals(arg1.getName())) {
Float money = (float) (0.8*(Float)arg2[0]);
returnValue = arg1.invoke(target, money);
}
return returnValue;
}
});
proxy.saleProduct(1000f);
*/
}
}
兩種方法運行的結果都是:
賣了800.0
寫到最後:用這種方式的(基於子類的動態代理)中,無需被代理類有什麼特殊的要求只需要是一個java的簡單類就行了,然後用到了這個類的生命;
還有一種基於接口的動態代理:jdk自帶的動態代理
https://blog.csdn.net/weixin_45127611/article/details/104523192