cglib代理
cglib代理主要通過對字節碼的操作,爲對象引入間接級別,以控制對象的訪問。我們知道Java中有一個動態代理也是做這個事情的,那我們爲什麼不直接使用Java動態代理,而要使用cglib呢?答案是cglib相比於JDK動態代理更加強大,JDK動態代理雖然簡單易用,但是其有一個致命缺陷是,只能對接口進行代理。如果要代理的類爲一個普通類、沒有接口,那麼Java動態代理就沒法使用了。
pom文件依賴
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
被代理對象
package cn.test.proxy.actor;
/**
* 目標對象:演員
*/
public class ArtActor {
/**
* 基本表演
*/
public void basicAct(Float money) {
System.out.println("演員【"+getActorName()+"】收到錢:"+money+",開始基本表演。");
}
/**
* 高難度表演
*/
public void difficultyAct(Float money) {
System.out.println("演員【"+getActorName()+"】收到錢:"+money+",開始高難度表演。");
}
/**
* 演員名稱
*/
public String getActorName(){
return "小花";
}
}
方法攔截器與代理類測試
package cn.test.proxy.play;
import cn.itheima.proxy.actor.ArtActor;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
/**
* 用戶:劇組
*/
public class Play {
public static void main(String[] args) {
/**
* 版本二:劇組通過經紀人人,找演員表演
* 實現方式:
* 第三方的cglib動態代理實現
* 涉及到的類:
* EnHancer
* 涉及到的方法:
* create()
* 參數:
* Class:被代理類的字節碼
* Callback:如何代理。這裏是實現增強的地方。相當於InvocationHandler
*/
// 創建目標對象(演員)
final ArtActor actor = new ArtActor();
// 創建代理對象(經紀人)
ArtActor actorProxy = (ArtActor)Enhancer.create(
actor.getClass(),
new MethodInterceptor() {
/**
*實現增強功能方法:intercept()。相當於invoke()
* 參數:
* proxy:代理對象引用。一般用不到
* method:當前執行的方法對象
* args:當前執行方法的參數列表
* methodProxy:當前方法對象的代理引用。一般用不到
*/
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 1.劇組找到經紀人
// 1.1.明確表演需求:方法名稱
String methodName = method.getName();
// 1.2.明確出場費用
Float money = (Float) args[0];
// 2.經紀人聯繫演員:是基本表演?還是高難度表演?給多少錢?
System.out.println("經紀人正在聯繫演員。");
// 2.1.是基本表演嗎?基本表演要求5000塊
Object retV = null;
if("basicAct".equals(methodName)){
if(money >= 5000){
System.out.println("基本表演,劇組錢給到位了。演員收下這個劇本。");
// 開始表演
retV = method.invoke(actor, money * 4 / 5);
}else{
System.out.println("劇組只給了:"+money+",錢不到位。演員表示檔期太滿。");
}
}
// 2.2.是高難度表演嗎?高難度表演要求10000塊
if("difficultyAct".equals(methodName)){
if(money >= 10000){
System.out.println("高難度表演,劇組錢給到位了。演員收下這個劇本。");
retV = method.invoke(actor,money*4/5);
}else{
System.out.println("劇組只給了:"+money+",錢不到位。演員直接表示拒絕這個劇本。");
}
}
return retV;
}
}
);
// 經紀人代理演員,開始表演
// 基本表演
actorProxy.basicAct(5000f);
System.out.println("----------------華麗麗分割線----------------");
// 高難度表演
actorProxy.difficultyAct(10000f);
}
}