• CGLib动态代理



     动态代理:

    在程序执行时,运用反射机制动态创建代理类,不须要程序猿编写源码.动态代理简化了编程工作,提高了系统的可扩展性,由于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;
    	}
    	
    	//获得被代理的对象
    	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动态代理的改进版。



  • 相关阅读:
    #张祖德#
    不说啥,放题
    ……
    点群的判别(四)
    lougu P4180 【模板】严格次小生成树[BJWC2010]
    20190227模拟
    20190226模拟
    Triangles
    Darling
    Suspenseful
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6912879.html
Copyright © 2020-2023  润新知