动态代理:
在程序运行时,运用反射机制动态创建代理类,不需要程序员编写源代码.动态代理简化了编程工作,提高了系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类.说到底,java.lang.reflect包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力.
具体说来,JDK动态代理中包含一个Proxy类和一个InvocationHandler接口.
public staticObject newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException{}
publicinterface InvocationHandler { publicObject invoke(Object proxy,Method method,Object[] args) throws Throwable; }
注意:以上说的是JDK的动态代理,JDK动态代理最大的缺点就是依靠接口实现,如果一些类没有接口,JDK动态代理就无能为力了。
面对JDK动态缺点,CGLib又发挥了它的怎样优势呢?
CGLib动态代理包含MethodProxy、Proxy类和一个接口MethodInterceptor
public Object invokeSuper(Object obj, Object[] args) throws Throwable { try { init(); FastClassInfo fci = fastClassInfo; return fci.f2.invoke(fci.i2, obj, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } }
public interface MethodInterceptor extends Callback { public Object intercept(Object obj, java.lang.reflect.Method method,Object[] args,MethodProxy proxy) throws Throwable; }
CGLib动态代理Demo:
没有实现接口的实现类:
//没有实现接口的打招呼类 public class greetingimpl { public void sayhello(String name) { System.out.println(name+" sayhello"); } }
CGLib动态代理类:
//CGLib动态代理类 public class CGLibDynamicProxy implements MethodInterceptor{ //单例模式创建代理对象 private static CGLibDynamicProxy instance=new CGLibDynamicProxy(); //空的构造方法 private CGLibDynamicProxy(){ } //返回代理对象的实例 public static CGLibDynamicProxy getInstance(){ return instance; } //获得被代理的对象 public <T> T getProxy(Class<T> cls){ return (T) Enhancer.create(cls, this); } //拦截被代理对象的方法,在前后分别执行before()和after()方法 @Override public Object intercept(Object target, Method method, Object[] args,MethodProxy proxy) throws Throwable { before(); //Object result=proxy.invokeSuper(target, args);//方式一:这是CGLib动态代理比JDK动态代理方式多出来的方法,效率更高 //Object result=proxy.invoke(target, args);//方式二:使用该方法报"栈溢出"错:Exception in thread "main" java.lang.StackOverflowError Object result=method.invoke(target, args);//方式三:这是JDK动态代理中使用的方式 after(); return result; } //在代理类的方法的方法前执行 public void before(){ System.out.println("Before"); } //在代理类的方法的方法后执行 public void after(){ System.out.println("After"); } }
Client类:
public class client { public static void main(String[] args) { greetingimpl greetingimpl=CGLibDynamicProxy.getInstance().getProxy(greetingimpl.class); greetingimpl.sayhello("CGLibDynamicProxy"); } }
打印结果:
有接口的实现类:
//实现接口的打招呼类 public class greetingimpl implements greeting{ public void sayhello(String name) { System.out.println(name+" sayhello"); } }
Client类:
public class client { public static void main(String[] args) { greeting greeting=CGLibDynamicProxy.getInstance().getProxy(greetingimpl.class); greeting.sayhello("CGLibDynamicProxy"); } }
使用相同的CGLib动态代理类
打印结果:总结:
CGLib动态代理在JDK动态代理的的基础上了做了解决了没有实现接口类的动态代理问题,其关键点体现在动态代理类所提供的方法的能力上稍做了些增强,可以说CGLib动态代理就是JDK动态代理的改进版。