今天看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);
- }
- }
- ..............省略其它辅助方法
- }
相关推荐
在本篇Spring学习笔记中,我们将探讨如何使用CGLIB库来实现AOP功能。 CGLIB(Code Generation Library)是一个强大的高性能的代码生成库,它被广泛用于动态代理和运行时织入AOP切面。在Spring中,如果目标类没有...
本学习笔记将深入探讨Spring AOP的核心概念、工作原理以及实际应用。 1. **核心概念** - **切面(Aspect)**:切面是关注点的模块化,包含业务逻辑之外的横切关注点,如日志、事务管理。 - **连接点(Join Point...
### hibernate框架学习笔记整理 #### 一、Hibernate框架简介 **Hibernate框架**是一种用于Java应用的**对象关系映射**(Object-Relational Mapping, ORM)解决方案,它允许开发者使用面向对象的方式操作数据库中的表...
《Spring技术内幕 学习笔记》是一份深入探讨Spring框架核心机制的学习资料,结合作者zzc1684在iteye博客上的博文,我们可以从中学习到Spring框架的多个重要知识点。Spring作为Java企业级应用开发的基石,其设计思想...
### Spring编程学习笔记知识点概述 #### 一、Spring框架简介 Spring框架是一个开源的轻量级Java开发框架,主要用于简化企业级应用的开发工作。它提供了全面的基础架构支持,包括但不限于依赖注入(Dependency ...
学习笔记涵盖了Hibernate的基础概念、配置、实体类的创建、数据类型映射、关系映射(一对一、一对多、多对多)、查询语言HQL、 Criteria API、CGLIB动态代理等核心内容。笔记详细记录了每个知识点的原理和实践步骤...
【标题】"Spring学习笔记(十四)"主要涵盖了Spring框架中的AOP(面向切面编程)和CGLIB库的应用,这两个知识点在Java开发中尤为重要,尤其是对于构建灵活、可维护的大型企业级应用。 首先,Spring框架是Java开发中...
### JPA 学习笔记详解 #### 一、JPA 概述 Java Persistence API (JPA) 是 Sun 公司提出的一种 Java 持久层标准,它为 Java 开发者提供了一种对象关系映射 (ORM) 的工具来管理 Java 应用程序中的关系型数据。JPA ...
【标题】"Spring学习笔记(十三)"主要涉及的是Spring框架中的AOP(面向切面编程)部分,特别是关于CGLIB动态代理的实现。在Spring中,AOP是一种强大的编程模型,它允许开发者定义“切面”,即关注点的模块化,如日志...
【标题】"Spring学习笔记(八)"主要涵盖了Spring框架中的动态代理机制,这是Spring AOP(面向切面编程)的核心技术之一。动态代理允许我们在不修改原有代码的情况下,为对象添加额外的功能,如日志、事务管理等。在这...
### Spring学习笔记:深入理解AOP与Annotation驱动的动态代理 #### 核心知识点解析: 在探讨Spring框架中AOP(面向切面编程)及基于Annotation的动态代理之前,我们首先需要了解AOP的基本概念及其在Spring中的实现...
在本篇Spring学习笔记中,我们将深入探讨Spring的几个关键知识点,包括其优点、AOP的实现原理以及声明式事务管理。 首先,Spring的优点在于它的轻量级特性,它不对现有类结构造成入侵,允许开发者专注于业务逻辑。...
### Spring2.5 学习笔记详解 #### 一、Spring 框架简介 Spring 是一个开源的轻量级 Java 开发框架,主要用于简化企业级应用的开发工作。Spring 提供了一系列强大的功能,比如控制反转 (Inversion of Control, IOC)...
在本篇"Spring 学习笔记六"中,我们将深入探讨Spring框架的核心概念和技术细节,同时结合源码分析,以提升对Spring的理解和应用能力。本文档主要关注Spring的依赖注入(Dependency Injection,DI)机制、AOP(面向切...
这个"spring学习笔记,包括源码学习"的资料很可能包含了一系列关于Spring框架的核心概念、配置、使用方法以及深入源码的解析。 首先,让我们来了解一下Spring框架的基础知识。Spring的核心特性是依赖注入,它允许...
【Spring 学习笔记四】 在本篇Spring学习笔记中,我们将深入探讨Spring框架的核心特性,包括依赖注入(Dependency Injection,DI)、AOP(面向切面编程)以及Spring的源码解析,同时也会介绍一些实用的开发工具。...
以下将详细介绍Spring学习笔记中的主要知识点。 **面向抽象编程** 面向抽象编程是一种设计原则,强调在代码中使用接口或抽象类,而不是具体实现类。这使得系统更具有灵活性,易于扩展和维护。在Spring框架中,我们...
本学习笔记将深入探讨动态SQL的概念及其在MyBatis中的应用,同时结合相关库如Javassist、CGLIB等进行解析。 首先,动态SQL的核心思想是避免硬编码大量的静态SQL语句,而是通过程序逻辑来动态生成SQL。这提高了代码...
### Spring2.5.6 学习笔记精粹解析 #### 一、Spring框架环境搭建与JAR包配置 在开始深入Spring框架的学习之前,首先需要确保开发环境正确配置Spring框架。按照“传智播客Spring2.5.6学习笔记最新整理”的指引,...