1、Spring的两种代理JDK和CGLIB的区别浅谈:
https://blog.csdn.net/u013126379/article/details/52121096
注:两种代理的实例,写的浅显易懂
2、Java动态代理分析:
https://blog.csdn.net/danchu/article/details/70146985
注:jdk动态代理的原理进行浅显易懂的讲解
动态生成的代理类本身类继承关系如下图:Proxy 类是它的父类,这个规则适用于所有由 Proxy 创建的动态代理类。而且该类还实现了其所代理的一组接口;
Proxy只能对interface进行代理,无法实现对class的动态代理。
观察动态生成的代理继承关系图可知原因,他们已经有一个固定的父类叫做Proxy,Java语法限定其不能再继承其他的父类
如下简单示例所示
public class DynamicProxy {
interface IHello{
void sayHello();
}
static class Hello implements IHello{
public void sayHello() {
System.out.println("hello world");
}
}
static class DynamicProxyTest implements InvocationHandler{
Object originalObj;
Object bind(Object originalObj){
this.originalObj = originalObj;
return Proxy.newProxyInstance(originalObj.getClass().getClassLoader(),
originalObj.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Welcome");
return method.invoke(originalObj,args);
}
}
public static void main(String[] args){
//设置这个值,在程序运行完成后,可以生成代理类
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
IHello hello = (IHello) new DynamicProxyTest().bind(new Hello());
hello.sayHello();
}
}
3、CGLIB(Code Generation Library)详解
https://blog.csdn.net/danchu/article/details/70238002
注:对cglib 进行浅显易懂的讲解
如下简单示例
public class SampleClass {
public void test(){
System.out.println("hello world");
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(SampleClass.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("before method run...");
Object result = proxy.invokeSuper(obj, args);
System.out.println("after method run...");
return result;
}
});
SampleClass sample = (SampleClass) enhancer.create();
sample.test();
}
}
一个使用CGLIB的小demo就完成了
Enhancer可能是CGLIB中最常用的一个类
Enhancer创建一个被代理对象的子类并且拦截所有的方法调用(包括从Object中继承的toString和hashCode方法)。
Enhancer不能够拦截final方法,例如Object.getClass()方法,这是由于Java final方法语义决定的。基于同样的道理,Enhancer也不能对fianl类进行代理操作。这也是Hibernate为什么不能持久化final class的原因
注意:
由于CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。
jdk动态代理和cglib 特点对比
| cglib | jdb动态代理 | |
代理接口 | yes | yes | |
代理普通的class | yes | no |
CGLIB和Java动态代理的区别
- Java动态代理只能够对接口进行代理,不能对普通的类进行代理(因为所有生成的代理类的父类为Proxy,Java类继承机制不允许多重继承);CGLIB能够代理普通类;
- Java动态代理使用Java原生的反射API进行操作,在生成类上比较高效;| CGLIB使用ASM框架直接对字节码进行操作,在类的执行过程中比较高效
4、cglib源码分析