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