`

CGLib学习笔记

    博客分类:
  • java
 
阅读更多

今天看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是被代理类和拦截器的桥梁

  

  1. package cn.java.cglibproxy;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. import net.sf.cglib.proxy.Enhancer;   
  6. import net.sf.cglib.proxy.MethodInterceptor;   
  7. import net.sf.cglib.proxy.MethodProxy;   
  8.   
  9. public class CglibProxy implements MethodInterceptor {   
  10.   
  11.     private Enhancer enhancer = new Enhancer();   
  12.        
  13.     public Object getProxy(Class<TestCglib> clazz){   
  14.            
  15.         enhancer.setSuperclass(clazz);   //设置父类(被代理类)以创建子类
  16.         enhancer.setCallback(this);   //设置拦截器:在这里有可能就设置当子类调用父类方法时便会调用拦截器方法intercept.
  17.            
  18.         return enhancer.create();   //创建被代理类的子类
  19.     }   
  20.        
  21.        
  22.     public Object intercept(Object obj, Method method, Object[] arg2,   
  23.             MethodProxy proxy) throws Throwable {   
  24.            
  25.         System.out.println("打印前");   
  26.            
  27.         Object result = proxy.invokeSuper(obj, arg2);   
  28.            
  29.            
  30.         System.out.println("打印后");   
  31.            
  32.         return result;   
  33.     }   
  34.   
  35. }  

 #3客户端程序:

 

  1. package cn.java.cglibproxy;   
  2.   
  3. public class TestCglibMain {   
  4.   
  5.     public static void main(String[] args) {   
  6.            
  7.         //初始化代理类   
  8.         CglibProxy proxy  =  new CglibProxy();   
  9.         //通过代理类创建被代理类的子类   
  10.         TestCglib test = (TestCglib)proxy.getProxy(TestCglib.class);   
  11.         //调用父类方法   -----当子类的对象调用父类方法时会调用拦截器进行拦截
  12.         test.pringSomthing();   
  13.            
  14.     }   
  15.   
  16. }  

 

http://elfasd.iteye.com/blog/1771226

java的动态代理只能对接口进行代理,如果一个类没有实现任何接口,则需要使用Cglib的动态代理技术,

 

cglib的一种实现简单地讲就是一句话:为代理类创建一个子类,并拦截这个子类对父类方法的调用。

 

这么说比较抽象,下面三个简单的类实现了cglib的动态代理

 

入口类:

TestCglibMain.java

 

Java代码 复制代码 收藏代码
  1. package cn.java.cglibproxy;   
  2.   
  3. public class TestCglibMain {   
  4.   
  5.     public static void main(String[] args) {   
  6.            
  7.         //初始化代理类   
  8.         CglibProxy proxy  =  new CglibProxy();   
  9.         //创建代理子类   
  10.         TestCglib test = (TestCglib)proxy.getProxy(TestCglib.class);   
  11.         //调用父类方法   
  12.         test.pringSomthing();   
  13.            
  14.     }   
  15.   
  16. }  
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

 

Java代码 复制代码 收藏代码
  1. package cn.java.cglibproxy;   
  2.   
  3. public class TestCglib {   
  4.   
  5.     public void pringSomthing(){   
  6.         System.out.println("printSomthing is now!!!");   
  7.     }   
  8. }  

 

cglib代理实现类:

CglibProxy.java

 

Java代码 复制代码 收藏代码
  1. package cn.java.cglibproxy;   
  2.   
  3. import java.lang.reflect.Method;   
  4.   
  5. import net.sf.cglib.proxy.Enhancer;   
  6. import net.sf.cglib.proxy.MethodInterceptor;   
  7. import net.sf.cglib.proxy.MethodProxy;   
  8.   
  9. public class CglibProxy implements MethodInterceptor {   
  10.   
  11.     private Enhancer enhancer = new Enhancer();   
  12.        
  13.     public Object getProxy(Class<TestCglib> clazz){   
  14.            
  15.         enhancer.setSuperclass(clazz);   //设置父类(被代理类)以创建子类
  16.         enhancer.setCallback(this);   //设置拦截器
  17.            
  18.         return enhancer.create();   //创建被代理类的子类
  19.     }   
  20.        
  21.        
  22.     public Object intercept(Object obj, Method method, Object[] arg2,   
  23.             MethodProxy proxy) throws Throwable {   
  24.            
  25.         System.out.println("打印前");   
  26.            
  27.         Object result = proxy.invokeSuper(obj, arg2);   
  28.            
  29.            
  30.         System.out.println("打印后");   
  31.            
  32.         return result;   
  33.     }   
  34.   
  35. }  

 

 

执行入口程序,打印结果:

打印前
printSomthing is now!!!
打印后

 

 

###对于Hibernate中使用CGLib来生成代理从而实现缓存的理解,它主要是在intercept方法中检查,如果是id就返回就调用父类的方法,并且此时父类的属性除了id外全部是空的,但如果不是id而是其它属性时就需要查数据库了(load)http://superleo.iteye.com/blog/243322

  1.  
  2. public class LazyInitializerImpl<T, PK extends Serializable> implements  
  3.  
  4.         LazyInitializer<T, PK>, MethodInterceptor {   
  5.   
  6.     private Session<T, PK> session; // 绑定的session对象   
  7.     private boolean isAlreadyInit = false// 是否已经查询过数据库   
  8.     private T targetObject; // 目标对象   
  9.   
  10.     // 通CGLib生成的对象,如果设置了此拦截器,那么其方法每次调用时,都会触发此方法   
  11.     public Object intercept(Object obj, Method method, Object[] args,   
  12.             MethodProxy proxy) throws Throwable {   
  13.         // 继续利用反射得到代理对象的标有@Id的主键属性   
  14.         Class<?> clas = obj.getClass();   
  15.         Field field = getPrimaryKey(clas);   
  16.   
  17.         assert (field != null);   
  18.         // 如果当前调用的方法是标注为@Id的话,那么就不从数据库里取,直接返回代理   
  19.         // 即如果是getId()的话,直接用代理调用;如果是getName()的话,那就必须查询数据库,取出实际对象,并进行相应的调用了   
  20.         if (method.getName().toLowerCase().indexOf(field.getName()) > -1) {   
  21.             return proxy.invokeSuper(obj, args);   
  22.         } else {   
  23.             if (!isAlreadyInit) {   
  24.                 field.setAccessible(true);   
  25.                 // session.get方法直接查询数据库,并将ResultSet结果组将成User对象   
  26.                 targetObject = session.get((PK) field.get(obj));   
  27.                 isAlreadyInit = true;   
  28.             }   
  29.             return method.invoke(targetObject, args);   
  30.   
  31.         }   
  32.   
  33.     }   
  34.   
  35.         ..............省略其它辅助方法   
  36.   
  37. }  
分享到:
评论

相关推荐

    CGLIB简介 CGLIB简介 CGLIB简介 CGLIB简介

    CGLIB简介CGLIB简介CGLIB简介CGLIB简介CGLIB简介

    AOP-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开发工具 cglib-3.2.4...

    cglib-3.1-API文档-中文版.zip

    赠送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

    cglib_cglib.zip

    cglib.zip

    cglib.jar下载

    CGLIB介绍与原理(部分节选自网络) 一、什么是CGLIB? CGLIB是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要...

    cglib包及依赖汉cglib3.1和asm4.2

    cglib包及依赖汉cglib3.1和asm4.2,主要作用是用户代理,代理为控制要访问的目标对象提供了一种途径。当访问对象时,它引入了一个间接的层。JDK自从1.3版本开始,就引入了动态代理,并且经常被用来动态地创建代理。...

    cglib_cglib3.2_remain3gr_cglibjar包_cglib.jar_

    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简单实现Spring体系(Ioc+Aop+Mvc)...

    CGLib3.2.5依赖包及源码

    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及其依赖包

    cglib实现动态代理所依赖的jar包 在学习spring中会用到

    CGLIB需要的asm-2.2.3.jar和cglib-nodep-2.2.jar

    里面包含完整的cglib-nodep-2.2.jar和asm-2.2.3.jar,放心下载

    Cglib3.3.0最新版jar包

    Cglib最新版本的2个jar包,分别是cglib-3.3.0.jar和cglib-nodep-3.3.0.jar,压缩后上传,方便大家使用。

    CGLIB-DOC说明

    CGLIB-DOC,CGLIB说明文件.

    Cglib的jar文件 Cglib.zip

    Cglib的jar文件,包含:asm.jar、asm-commons.jar、asm-tree.jar、cglib-2.2.jar 四个jar包

    cglib-2.2.3.jar

    SSH2环境搭建asm和cglib的包冲突,使用cglib-2.2.3.jar

    cglib-nodep-3.2.4-API文档-中文版.zip

    赠送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-...

    cglib-3.3.0-API文档-中文版.zip

    赠送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源码

    cglib-2.2.2源码

Global site tag (gtag.js) - Google Analytics