在程序運行期,創建目標對象的代理對象,對目標對象中的方法進行功能性增強的一種技術; 它就是JVM中,對象方法的攔截器
write less do more!!
回顧OOP(面向對象編程)
- 三大特征:封裝、繼承和多態
- 比如說,有Dog類、Cat類、Horse類,它們都有eat方法,run方法,按照OOP的編程思想,那么我們可以抽象出父類Animal,在父類中放置相同的屬性或者方法,這樣來避免多子類中重復的代碼。
- 一切皆對象,很牛逼了,其實它有缺陷!

OOP是縱向抽取和繼承體系,OOP很多場合都能夠解決我們的問題【代碼重復問題】,但是有一些場合,也有它處理不了的需要被解決的大量的代碼重復問題。
1.1 什么是動態代理?
==動態代理就是,在程序運行期,創建目標對象的代理對象,并對目標對象中的方法進行功能性增強的一種技術==。在生成代理對象的過程中,目標對象不變,代理對象中的方法是目標對象方法的增強方法。可以理解為運行期間,對象中方法的動態攔截,在攔截方法的前后執行功能操作。
代理類在程序運行期間,創建的代理對象稱之為動態代理對象。這種情況下,創建的代理對象,并不是事先在JAVA代碼中定義好的。而是在運行期間,根據我們在動態代理對象中的“指示”,動態生成的。也就是說,你想獲取哪個對象的代理,動態代理就會為你動態的生成這個對象的代理對象。
動態代理可以對被代理對象的方法進行功能增強。有了動態代理的技術,那么就可以在不修改方法源碼的情況下,增強被代理對象的方法的功能,在方法執行前后做任何你想做的事情。
創建代理對象的兩個方法:
//JDK動態代理
Proxy.newProxyInstance(三個參數);
//CGLib動態代理
Enhancer.create(兩個參數);
正常類創建對象的過程:

動態代理創建代理對象的過程:

1.2 兩種常用的動態代理方式
- 基于接口的動態代理
- 提供者:JDK
- 使用JDK官方的Proxy類創建代理對象
- 注意:代理的目標對象必須實現接口
- 基于類的動態代理
- 提供者:第三方 CGLib
- 使用CGLib的Enhancer類創建代理對象
- 注意:如果報 asmxxxx 異常,需要導入 asm.jar包
public class LogProxy {
/**
* 生成對象的代理對象,對被代理對象進行所有方法日志增強
* 參數:原始對象
* 返回值:被代理的對象
* JDK 動態代理
* 基于接口的動態代理
* 被代理類必須實現接口
* JDK提供的
*/
public static Object getObject(final Object obj){
/**
* 創建對象的代理對象
* 參數一:類加載器
* 參數二:對象的接口
* 參數三:調用處理器,代理對象中的方法被調用,都會在執行方法。對所有被代理對象的方法進行攔截
*/
Object proxyInstance = Proxy.newProxyInstance(obj.getClass().getClassLoader()
, obj.getClass().getInterfaces(), new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法執行前
long startTime = System.currentTimeMillis();
Object result = method.invoke(obj, args);//執行方法的調用
//方法執行后
long endTime = System.currentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat();
System.out.printf(String.format("%s方法執行結束時間:%%s ;方法執行耗時:%%d%%n"
, method.getName()), sdf.format(endTime), endTime - startTime);
return result;
}
});
return proxyInstance;
}
/**
* 使用CGLib創建動態代理對象
* 第三方提供的的創建代理對象的方式CGLib
* 被代理對象不能用final修飾
* 使用的是Enhancer類創建代理對象
*/
public static Object getObjectByCGLib(final Object obj){
/**
* 使用CGLib的Enhancer創建代理對象
* 參數一:對象的字節碼文件
* 參數二:方法的攔截器
*/
Object proxyObj = Enhancer.create(obj.getClass(), new MethodInterceptor() {
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//方法執行前
long startTime = System.currentTimeMillis();
Object invokeObject = method.invoke(obj, objects);//執行方法的調用
//方法執行后
long endTime = System.currentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat();
System.out.printf(String.format("%s方法執行結束時間:%%s ;方法執行耗時:%%d%%n"
, method.getName()), sdf.format(endTime), endTime - startTime);
return invokeObject;
}
});
return proxyObj;
}
}