动态代理:
在程序执行时,运用反射机制动态创建代理类,不须要程序猿编写源码.动态代理简化了编程工作,提高了系统的可扩展性,由于Java反射机制能够生成随意类型的动态代理类.说究竟,java.lang.reflect包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力.
详细说来,JDK动态代理中包括一个Proxy类和一个InvocationHandler接口.
- 通过Proxy类为一个或多个接口动态地生成实现类,其方法是:
public staticObject newProxyInstance(ClassLoader loader, Class [] interfaces,InvocationHandler h) throws IllegalArgumentException{}
- 通过InvocationHandler接口,调用实现类的方法,从而完毕终于操作.其方法是:
publicinterface InvocationHandler {publicObject invoke(Object proxy,Method method,Object[] args) throws Throwable;}
注意:以上说的是JDK的动态代理,JDK动态代理最大的缺点就是依靠接口实现,假设一些类没有接口,JDK动态代理就无能为力了。
面对JDK动态缺点,CGLib又发挥了它的如何优势呢?
CGLib动态代理包括MethodProxy、Proxy类和一个接口MethodInterceptor
- 通过MethodProxy、Proxy类获得实现类,方法例如以下:
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(); } }
- 通过MethodInterceptor接口拦截被代理对象的方法。从而完毕终于操作
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; } //获得被代理的对象 publicT getProxy(Class 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动态代理的改进版。