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);
}
}