`

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. }  
分享到:
评论

相关推荐

    Spring学习笔记(14)----使用CGLIB实现AOP功能

    在本篇Spring学习笔记中,我们将探讨如何使用CGLIB库来实现AOP功能。 CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它被广泛用于动态代理和运行时织入AOP切面。在Spring中,如果目标类没有...

    spring aop 学习笔记

    本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际应用。 1. **核心概念** - **切面(Aspect)**:切面是关注点的模块化,包含业务逻辑之外的横切关注点,如日志、事务管理。 - **连接点(Join Point...

    hibernate框架学习笔记整理

    ### hibernate框架学习笔记整理 #### 一、Hibernate框架简介 **Hibernate框架**是一种用于Java应用的**对象关系映射**(Object-Relational Mapping, ORM)解决方案,它允许开发者使用面向对象的方式操作数据库中的表...

    Spring技术内幕 学习笔记

    《Spring技术内幕 学习笔记》是一份深入探讨Spring框架核心机制的学习资料,结合作者zzc1684在iteye博客上的博文,我们可以从中学习到Spring框架的多个重要知识点。Spring作为Java企业级应用开发的基石,其设计思想...

    Spring编程学习笔记

    ### Spring编程学习笔记知识点概述 #### 一、Spring框架简介 Spring框架是一个开源的轻量级Java开发框架,主要用于简化企业级应用的开发工作。它提供了全面的基础架构支持,包括但不限于依赖注入(Dependency ...

    Hibernate学习笔记源码及文档

    学习笔记涵盖了Hibernate的基础概念、配置、实体类的创建、数据类型映射、关系映射(一对一、一对多、多对多)、查询语言HQL、 Criteria API、CGLIB动态代理等核心内容。笔记详细记录了每个知识点的原理和实践步骤...

    spring学习笔记(十四)

    【标题】"Spring学习笔记(十四)"主要涵盖了Spring框架中的AOP(面向切面编程)和CGLIB库的应用,这两个知识点在Java开发中尤为重要,尤其是对于构建灵活、可维护的大型企业级应用。 首先,Spring框架是Java开发中...

    jpa学习笔记

    ### JPA 学习笔记详解 #### 一、JPA 概述 Java Persistence API (JPA) 是 Sun 公司提出的一种 Java 持久层标准,它为 Java 开发者提供了一种对象关系映射 (ORM) 的工具来管理 Java 应用程序中的关系型数据。JPA ...

    spring学习笔记(十三)

    【标题】"Spring学习笔记(十三)"主要涉及的是Spring框架中的AOP(面向切面编程)部分,特别是关于CGLIB动态代理的实现。在Spring中,AOP是一种强大的编程模型,它允许开发者定义“切面”,即关注点的模块化,如日志...

    spring学习笔记(八)

    【标题】"Spring学习笔记(八)"主要涵盖了Spring框架中的动态代理机制,这是Spring AOP(面向切面编程)的核心技术之一。动态代理允许我们在不修改原有代码的情况下,为对象添加额外的功能,如日志、事务管理等。在这...

    Spring学习笔记

    ### Spring学习笔记:深入理解AOP与Annotation驱动的动态代理 #### 核心知识点解析: 在探讨Spring框架中AOP(面向切面编程)及基于Annotation的动态代理之前,我们首先需要了解AOP的基本概念及其在Spring中的实现...

    Spring学习笔记1

    在本篇Spring学习笔记中,我们将深入探讨Spring的几个关键知识点,包括其优点、AOP的实现原理以及声明式事务管理。 首先,Spring的优点在于它的轻量级特性,它不对现有类结构造成入侵,允许开发者专注于业务逻辑。...

    Spring2.5学习笔记

    ### Spring2.5 学习笔记详解 #### 一、Spring 框架简介 Spring 是一个开源的轻量级 Java 开发框架,主要用于简化企业级应用的开发工作。Spring 提供了一系列强大的功能,比如控制反转 (Inversion of Control, IOC)...

    Spring 学习笔记六

    在本篇"Spring 学习笔记六"中,我们将深入探讨Spring框架的核心概念和技术细节,同时结合源码分析,以提升对Spring的理解和应用能力。本文档主要关注Spring的依赖注入(Dependency Injection,DI)机制、AOP(面向切...

    spring学习笔记,包括源码学习

    这个"spring学习笔记,包括源码学习"的资料很可能包含了一系列关于Spring框架的核心概念、配置、使用方法以及深入源码的解析。 首先,让我们来了解一下Spring框架的基础知识。Spring的核心特性是依赖注入,它允许...

    Spring 学习笔记四

    【Spring 学习笔记四】 在本篇Spring学习笔记中,我们将深入探讨Spring框架的核心特性,包括依赖注入(Dependency Injection,DI)、AOP(面向切面编程)以及Spring的源码解析,同时也会介绍一些实用的开发工具。...

    Spring的学习笔记

    以下将详细介绍Spring学习笔记中的主要知识点。 **面向抽象编程** 面向抽象编程是一种设计原则,强调在代码中使用接口或抽象类,而不是具体实现类。这使得系统更具有灵活性,易于扩展和维护。在Spring框架中,我们...

    学习笔记动态SQL:Demo.zip

    本学习笔记将深入探讨动态SQL的概念及其在MyBatis中的应用,同时结合相关库如Javassist、CGLIB等进行解析。 首先,动态SQL的核心思想是避免硬编码大量的静态SQL语句,而是通过程序逻辑来动态生成SQL。这提高了代码...

    传智播客Spring2.5.6学习笔记最新整理

    ### Spring2.5.6 学习笔记精粹解析 #### 一、Spring框架环境搭建与JAR包配置 在开始深入Spring框架的学习之前,首先需要确保开发环境正确配置Spring框架。按照“传智播客Spring2.5.6学习笔记最新整理”的指引,...

Global site tag (gtag.js) - Google Analytics