基于子类的动态代理
要求:
1.被代理类不能是最终类,不能被finaly修饰
提供者:第三方 CGlib
涉及的类:Enhancer
2.创建代理对象的方法:
create(Class,Callback)
参数:
Class: 被代理类的字节码文件对象
Callback:增强的代码,通常都是些一个接口的实现类或匿名内部类,
我们在使用时一般都是使用Callback接口的子接口:MethodInterceptor
代码演示:
使用第三方jar包,将CBlib包导入到资源中 (可以到Maven仓库下载)
创建一个Actor作为 被代理类
//本类表示演员类
public class Actor{
//简单演出
public void simpleShow(Integer money) {
System.out.println("简单演出一次"+money+"元");
}
//危险演出
public void riskShow(Integer money) {
System.out.println("危险演出一次"+money+"元");
}
}
Test
public class Test {
public static void main(String[] args) {
//创建演员对象 ,被代理对象
Actor a = new Actor();
//通过Enhancer.creater() 创建代理对象
Actor CglibActor = (Actor)Enhancer.create(a.getClass(), new MethodInterceptor(){
/*
* 重写MethodInterceptor的 intercept方法
* 调用的代理对象的所有方法都会先执行 intercept方法
*
* 参数:
* Object proxy:代理对象的引用
* Method method:被调用的方法对象
* Object[] args:传递给目标对象的参数
* MethodProxy proxy2:代理对象的方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy proxy2) throws Throwable {
//-----判断money的值:简单演出不低于10000块才演出,危险演出不低于20000才演出--------
//获取money的值
Integer money = (Integer)args[0];
//定义一个null对象 ,接收代理类方法放回的结果,作为invoke方法的返回值
Object obj = null;
//如果是简单方法
if("simpleShow".equals(method.getName())) {
//money 不低于10000 才演出
if(money>=10000) {
/*
* method.invoke(obj,args )
* obj - 从中调用底层方法的对象
* args - 用于方法调用的参数
*/
obj = method.invoke(a,money);//obj 接收方法的返回值,即使是void也有返回值对象
}
}
//如果是危险方法
if("riskShow".equals(method.getName())) {
if(money>=20000) {
obj = method.invoke(a,money);
}
}
return obj;//invoke 方法会返回值,而返回值void,也是一个Void对象
}
});
//通过代理对象,调用演员演出
CglibActor.simpleShow(5000);
CglibActor.riskShow(40000);
}
}
输出:
危险演出一次40000元