Spring AOP中两种动态代理方式

来源:互联网 发布:java手动 buildpath 编辑:程序博客网 时间:2024/06/01 16:19

1. JDk 反射机制

    实现java.lang.reflect.InvocationHandler接口,复写其中的invoke方法。

    生成代理核心方法是:

     

    从 obj.getClass().getInterfaces() 可以看出,如果直接用 JDK 的反射需要创建接口,比较麻烦。

2.cglib

    cglib(Code Generation Library)是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。cglib封装了asm,可以在运行期动态生成新的class。asm 是一个强大的 Java 字节码生成框架,和 BCEL 或者 SERP 很类似,但是小很多,可以动态修改 java 字节码。

    image

    cgLib 可以不用接口,它底层调用asm 动态生成一个代理类去覆盖父类中非 final 的方法,然后实现 MethodInterceptor 接口的 intercept 方法,这样以后直接调用重写的方法,比 JDK 要快。但是加载 cglib 消耗时间比直接 JDK 反射时间长,开发的过程中,如果是反复动态生成新的代理类推荐用 JDK 自身的反射,反之用 cglib。

    顺便了解了一下cglib在Hibernate延迟加载中的应用:

    先看如下语句,

     

    在session.load()执行时,并没有查询数据库,只有在执行user.getName()方法时才真正去获取name属性的值,这就是延迟加载的应用,通过这种方式可以降低系统资源的耗费,从而提升效率。

    在执行session.load()方法时,返回的User对象其实是User类的一个代理对象,在Hibernate中通过使用cglib来实现动态构造一个目标对象的代理对象,并在代理类对象中包含目标对象的属性和方法,而且所有属性均被复制为null。当调用user.getName()方法,此时Hibernate通过cglib的回调机制,实际上调用CGLIB$CALLBACK_0.getName()方法,当调用该方法时,Hibernate会检查CGLIB$CALLBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName()方法,如果为空,则会到数据库进行查询,并将查询到的结果构造为目标对象复制到CGLIB$CALLBACK_0.target属性中。

    以下转载一个实例,说明cglib的使用:

    原文链接:http://www.blogjava.net/Good-Game/archive/2007/11/05/158192.html