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动态代理的改进版。



原文地址:https://www.cnblogs.com/clnchanpin/p/6912879.html