目录
CGLib动态代理
程序执行时通过ASM(开源的Java字节码编辑库,操作字节码)jar包动态地为被代理类生成一个代理子类,通过该代理子类创建代理对象,由于存在继承关系,所以父类不能使用final修饰。
过程1.首先导入jar包
2.定义一个接口
public interface ICalculatorService { int add(int a,int b); int sub(int a,int b); int mul(int a,int b); int div(int a,int b); }
3.接口实现类
public class CalculatorService implements ICalculatorService { @Override public int add(int a, int b) { int result = a+b; return result; } @Override public int sub(int a, int b) { int result = a-b; return result; } @Override public int mul(int a, int b) { int result = a*b; return result; } @Override public int div(int a, int b) { int result = a/b; return result; } }
4.CGlib
import java.lang.reflect.Method; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class ProxyFactory { static ICalculatorService target;// 目标对象 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() + "--"+name + "--method begins."); System.out.println(target.getClass().getName() + ":Parameters of the " + name + " method: [" + args[0] + "," + args[1] + "]"); Object result = method.invoke(target, args); System.out.println(target.getClass().getName() + ":Result of the " + name + " method:" + result); System.out.println(target.getClass().getName() + ":The " + name + " method ends."); return result; } }; public static Object getProxy(ICalculatorService target) { ProxyFactory.target = target; Enhancer enhancer = new Enhancer(); // Enhancer类 类似于JDK调用add方法增加了一些打印的信息 enhancer.setSuperclass(target.getClass()); // superclass enhancer.setCallback(callback); return enhancer.create(); // 代理谁,返回的代理对象 } }
5.测试类
public class Test { public static void main(String[] args) { CalculatorService cService = (CalculatorService) ProxyFactory.getProxy(new CalculatorService()); System.out.println("cService--------->" + cService.getClass().getName()); int result = cService.add(1, 2); // cService存放的是由Proxy创建的实现的ICalculatorService的一个匿名内部类 // cService.add(1, 2);调用的是由proxy类创建的匿名内部类对象中的add方法 System.out.println(result); } }
运行结果:
注意:CGlib生成的动态代理对象所对应的类是目标对象CalculatorService类的子类,两者是父子关系
JDK动态代理与CGLib动态代理区别:
1、JDK动态代理基于接口实现,所以实现JDK动态代理,必须先定义接口;CGLib动态代理基于类实现;
2、JDK动态代理机制是委托机制,委托hanlder调用原始实现类方法;CGLib则使用继承机制,被代理类和代理类是继承关系,所以代理类是可以赋值给被代理类的,如果被代理类有接口,那么代理类也可以赋值给接口。
动态代理优点:
1、静态代理在程序执行前需手动创建代理类,如果需要很多代理类,每一个都手动创建不仅浪费时间,而且可能产生大量重复性代码,此时我们就可以采用动态代理。
2、动态代理通过InvocationHandler接口invoke方法或MethodInterceptor接口intercept方法为被代理对象中的方法增加额外功能,这种方式比静态代理中通过代理类逐一为被代理对象中的方法增加额外功能,更加的灵活。