今天看Hibernate时发现延迟加载用到CGLib来返回代理对象,为了更深入理解CGLib特收集以下博文:
学习后总结
#1首先确定被代理类
package cn.java.cglibproxy; public class TestCglib { public void pringSomthing(){ System.out.println("printSomthing is now!!!"); } }
#2写一个代理类,这个代理类要实现MethodIntercepter接口,它主要做两件事情,第一件是提供一个创建被代理类子类的方法,可以通过CGLib API 比如Enhancer来实现,第二件是重写intercept方法以便在子类调用父类的方法时进行拦截,从而实现代理概念===>其实第一件事情不必需在拦截器中作,可以在客户端程序中写,把实现MethodIntercepter的类单纯看成是一个拦截器就可以了,只不过要将拦截器接口显示赋给Enhancer的setCallback方法,也就是为其设置拦截器。实际在本例中enhancer.setCallback(this); 也是执行设置拦截器的操作,如果在客户端中写,需用具体的拦截器对象代替this.相当enhancer是被代理类和拦截器的桥梁
- package cn.java.cglibproxy;
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class CglibProxy implements MethodInterceptor {
- private Enhancer enhancer = new Enhancer();
- public Object getProxy(Class<TestCglib> clazz){
- enhancer.setSuperclass(clazz); //设置父类(被代理类)以创建子类
- enhancer.setCallback(this); //设置拦截器:在这里有可能就设置当子类调用父类方法时便会调用拦截器方法intercept.
- return enhancer.create(); //创建被代理类的子类
- }
- public Object intercept(Object obj, Method method, Object[] arg2,
- MethodProxy proxy) throws Throwable {
- System.out.println("打印前");
- Object result = proxy.invokeSuper(obj, arg2);
- System.out.println("打印后");
- return result;
- }
- }
#3客户端程序:
- package cn.java.cglibproxy;
- public class TestCglibMain {
- public static void main(String[] args) {
- //初始化代理类
- CglibProxy proxy = new CglibProxy();
- //通过代理类创建被代理类的子类
- TestCglib test = (TestCglib)proxy.getProxy(TestCglib.class);
- //调用父类方法 -----当子类的对象调用父类方法时会调用拦截器进行拦截
- test.pringSomthing();
- }
- }
http://elfasd.iteye.com/blog/1771226
java的动态代理只能对接口进行代理,如果一个类没有实现任何接口,则需要使用Cglib的动态代理技术,
cglib的一种实现简单地讲就是一句话:为代理类创建一个子类,并拦截这个子类对父类方法的调用。
这么说比较抽象,下面三个简单的类实现了cglib的动态代理
入口类:
TestCglibMain.java
- package cn.java.cglibproxy;
- public class TestCglibMain {
- public static void main(String[] args) {
- //初始化代理类
- CglibProxy proxy = new CglibProxy();
- //创建代理子类
- TestCglib test = (TestCglib)proxy.getProxy(TestCglib.class);
- //调用父类方法
- test.pringSomthing();
- }
- }
package cn.java.cglibproxy; public class TestCglibMain { public static void main(String[] args) { //初始化代理类 CglibProxy proxy = new CglibProxy(); //创建代理子类 TestCglib test = (TestCglib)proxy.getProxy(TestCglib.class); //调用父类方法 test.pringSomthing(); } }
被代理类:
TestCglib.java
- package cn.java.cglibproxy;
- public class TestCglib {
- public void pringSomthing(){
- System.out.println("printSomthing is now!!!");
- }
- }
cglib代理实现类:
CglibProxy.java
- package cn.java.cglibproxy;
- import java.lang.reflect.Method;
- import net.sf.cglib.proxy.Enhancer;
- import net.sf.cglib.proxy.MethodInterceptor;
- import net.sf.cglib.proxy.MethodProxy;
- public class CglibProxy implements MethodInterceptor {
- private Enhancer enhancer = new Enhancer();
- public Object getProxy(Class<TestCglib> clazz){
- enhancer.setSuperclass(clazz); //设置父类(被代理类)以创建子类
- enhancer.setCallback(this); //设置拦截器
- return enhancer.create(); //创建被代理类的子类
- }
- public Object intercept(Object obj, Method method, Object[] arg2,
- MethodProxy proxy) throws Throwable {
- System.out.println("打印前");
- Object result = proxy.invokeSuper(obj, arg2);
- System.out.println("打印后");
- return result;
- }
- }
执行入口程序,打印结果:
打印前
printSomthing is now!!!
打印后
###对于Hibernate中使用CGLib来生成代理从而实现缓存的理解,它主要是在intercept方法中检查,如果是id就返回就调用父类的方法,并且此时父类的属性除了id外全部是空的,但如果不是id而是其它属性时就需要查数据库了(load)http://superleo.iteye.com/blog/243322
-
- public class LazyInitializerImpl<T, PK extends Serializable> implements
-
- LazyInitializer<T, PK>, MethodInterceptor {
- private Session<T, PK> session; // 绑定的session对象
- private boolean isAlreadyInit = false; // 是否已经查询过数据库
- private T targetObject; // 目标对象
- // 通CGLib生成的对象,如果设置了此拦截器,那么其方法每次调用时,都会触发此方法
- public Object intercept(Object obj, Method method, Object[] args,
- MethodProxy proxy) throws Throwable {
- // 继续利用反射得到代理对象的标有@Id的主键属性
- Class<?> clas = obj.getClass();
- Field field = getPrimaryKey(clas);
- assert (field != null);
- // 如果当前调用的方法是标注为@Id的话,那么就不从数据库里取,直接返回代理
- // 即如果是getId()的话,直接用代理调用;如果是getName()的话,那就必须查询数据库,取出实际对象,并进行相应的调用了
- if (method.getName().toLowerCase().indexOf(field.getName()) > -1) {
- return proxy.invokeSuper(obj, args);
- } else {
- if (!isAlreadyInit) {
- field.setAccessible(true);
- // session.get方法直接查询数据库,并将ResultSet结果组将成User对象
- targetObject = session.get((PK) field.get(obj));
- isAlreadyInit = true;
- }
- return method.invoke(targetObject, args);
- }
- }
- ..............省略其它辅助方法
- }
相关推荐
CGLIB简介CGLIB简介CGLIB简介CGLIB简介CGLIB简介
AOP-CGLIB学习-实现简单的注解权限系统
开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4开发工具 cglib-3.2.4...
赠送jar包:cglib-3.1.jar; 赠送原API文档:cglib-3.1-javadoc.jar; 赠送源代码:cglib-3.1-sources.jar; 赠送Maven依赖信息文件:cglib-3.1.pom; 包含翻译后的API文档:cglib-3.1-javadoc-API文档-中文(简体)版...
cglib
cglib.zip
CGLIB介绍与原理(部分节选自网络) 一、什么是CGLIB? CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要...
cglib包及依赖汉cglib3.1和asm4.2,主要作用是用户代理,代理为控制要访问的目标对象提供了一种途径。当访问对象时,它引入了一个间接的层。JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理。...
cglib 的jar包,用于做动态代理的,但是版本太高不知道会不会有影响
基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)基于Cglib简单实现Spring体系(Ioc+Aop+Mvc)...
cglib-3.2.5.jar、cglib-nodep-3.2.5.jar、cglib-RELEASE_3_2_5.tar.gz(源码)、cglib-RELEASE_3_2_5.zip(源码)
cglib实现动态代理所依赖的jar包 在学习spring中会用到
里面包含完整的cglib-nodep-2.2.jar和asm-2.2.3.jar,放心下载
Cglib最新版本的2个jar包,分别是cglib-3.3.0.jar和cglib-nodep-3.3.0.jar,压缩后上传,方便大家使用。
CGLIB-DOC,CGLIB说明文件.
Cglib的jar文件,包含:asm.jar、asm-commons.jar、asm-tree.jar、cglib-2.2.jar 四个jar包
SSH2环境搭建asm和cglib的包冲突,使用cglib-2.2.3.jar
赠送jar包:cglib-nodep-3.2.4.jar; 赠送原API文档:cglib-nodep-3.2.4-javadoc.jar; 赠送源代码:cglib-nodep-3.2.4-sources.jar; 赠送Maven依赖信息文件:cglib-nodep-3.2.4.pom; 包含翻译后的API文档:cglib-...
赠送jar包:cglib-3.3.0.jar; 赠送原API文档:cglib-3.3.0-javadoc.jar; 赠送源代码:cglib-3.3.0-sources.jar; 赠送Maven依赖信息文件:cglib-3.3.0.pom; 包含翻译后的API文档:cglib-3.3.0-javadoc-API文档-...
cglib-2.2.2源码