导入jar包
asm-7.0.jar
cglib-3.2.10.jar
仍然以加法运算为例
//定义目标对象的类和方法
class CalculatorService{
public int add(int a, int b) {
int result = a+b;
return result;
}
}
public class ProxyFactory {
static CalculatorService target; //目标对象
//MethodInterceptor接口继承自Callback接口
static Callback callback=new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//第一个参数对象是代理对象
System.out.println(target+"111"+proxy.getClass().getName());
return 0; //将来调用的目标方法的返回值
}
};
public static Object getProxy(CalculatorService target){
ProxyFactory.target=target;
Enhancer enhancer=new Enhancer();
enhancer.setSuperclass(target.getClass());
//用CGLib的方式实现动态代理,所生成的对象对应的类,是目标对象对应的CalculatorService类的子类;jdk动态代理是同级的关系
enhancer.setCallback(callback);
return enhancer.create();
}
}
class Test {
public static void main(String[] args) {
CalculatorService calculatorService = (CalculatorService)ProxyFactory.getProxy(new CalculatorService());
int result=calculatorService.add(1, 2);
System.out.println(result);
}
}
运行测试类,输出结果
com.replace.cg.CalculatorService@121714c111com.replace.cg.CalculatorService$$EnhancerByCGLIB$$481ab534
0
修改内部类中的代码,关联需求
static Callback callback=new MethodInterceptor() {
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//第一个参数对象是代理对象
String name=method.getName();
System.out.println(target.getClass().getName()+" the "+name+" method begins");
Object result=method.invoke(target, args);
System.out.println(target.getClass().getName()+" the result of "+name+" method is:"+result);
System.out.println(target.getClass().getName()+" the "+name+" method ends");
return result; //将来调用的目标方法的返回值
}
};
再次运行测试类,输出
com.replace.cg.CalculatorService the add method begins
com.replace.cg.CalculatorService the result of add method is:3
com.replace.cg.CalculatorService the add method ends
3
接下来我们要证明,目标对象CalculatorService target和测试类中的代理对象new CalculatorService()到底是什么关系
我们需要打印出产生动态对象的类,这个类也是临时的,
//测试类的主方法中添加如下代码
//生成使用CGlib创建动态代理对象的class文件
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\class");
控制台输出
CGLIB debugging enabled, writing to 'D:\class'
com.replace.cg.CalculatorService the add method begins
com.replace.cg.CalculatorService the result of add method is:3
com.replace.cg.CalculatorService the add method ends
3
D盘生成如下路径文件
复制文件到lib双击
这个文件对应的是是动态产生代理对象的类,观察代码可知extends
这就可以证明CGLib动态代理对象产生的动态代理对象 是我们目标类对象的子对象
总结
研究使用CGLib实现动态代理
CGLib动态代理
程序执行时通过ASM(开源的Java字节码编辑库,操作字节码)jar包动态地为被代理类生成一个代理子类,通过该代理子类创建代理对象,由于存在继承关系,所以父类不能使用final修饰。
JDK动态代理与CGLib动态代理区别:
1、JDK动态代理基于接口实现,所以实现JDK动态代理,必须先定义接口;CGLib动态代理基于类实现;
2、JDK动态代理机制是委托机制,委托hanlder调用原始实现类方法;CGLib则使用继承机制,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。
动态代理优点:
1、静态代理在程序执行前需手动创建代理类,如果需要很多代理类,每一个都手动创建不仅浪费时间,而且可能产生大量重复性代码,此时我们就可以采用动态代理。
2、动态代理通过InvocationHandler接口invoke方法或MethodIn