`
justry28
  • 浏览: 5904 次
  • 性别: Icon_minigender_1
  • 来自: 厦门
最近访客 更多访客>>
社区版块
存档分类
最新评论

不小心走入了cglib的误区

    博客分类:
  • java
阅读更多
这2天在学习CGLIB,一时兴起用CGLIB实现了一个管理hibernate事务的类,用来在业务层处理事务。

首先来看一下代理类,代码如下
package com.test;

import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.linbs.core.common.hibernate.HibernateUtil;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 使用CGLIB进行事务处理设置
 * @author linbs
 */
public class TransactionDAOProxy implements MethodInterceptor {
	
	private static Log logger = LogFactory.getLog(TransactionDAOProxy.class);
	
	private Enhancer enhancer=new Enhancer();
	
	public Object getDAO(Class clz){
        enhancer.setSuperclass(clz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
	public Object intercept(Object obj, Method method, Object[] args,
			MethodProxy proxy) throws Throwable {
		Session session = null;
		Transaction tx = null;
		Object result = null;
		
		try{
			session = HibernateUtil.getSession();
			tx = session.beginTransaction();
			result = proxy.invokeSuper(obj, args);
			tx.commit();
			session.flush();
		}catch(HibernateException e){
			try {
				tx.rollback();
			} catch (HibernateException e1) {
				logger.error(e1.getMessage());
				throw e;
			}
		}finally{
			try {
				HibernateUtil.closeSession();
			} catch (HibernateException e) {
				logger.error(e.getMessage());
				throw new Throwable("关闭session时出错!");
			}
		}
		return result;
	}

}

在result = proxy.invokeSuper(obj, args);这个地方调用了未进行代理的dao类的方法;

假设有个BaseHibernateDAO类 里面有这2个方法:
/**
	 * 取得当期进程的session对象
	 * @return
	 */
	public Session getSession() {
		return HibernateUtil.getSession();
	}
	
	/**
	 * 保存一个新的实体类的实例,并返回标识号
	 * @param obj
	 * @return
	 */
	public Serializable save(final Object obj) {
		return this.getSession().save(obj);
	}


注意在save 方法中又调用了getSession()这个方法;

现在来写一个测试类;
package com.test;

import com.linbs.core.common.hibernate.BaseHibernateDAO;
import com.linbs.usermanage.model.User;

public class Test {
	public static void main(String[] args){
		TransactionDAOProxy proxy = new TransactionDAOProxy();
		BaseHibernateDAO baseDAO = (BaseHibernateDAO)proxy.getDAO(BaseHibernateDAO.class);
		User user = new User();
		user.setUserName("abcProxy");
		user.setUserPwd("abcProxy");
		user.setEmail("abc@126.cn");
		baseDAO.save(user);
	}
}


该测试类对BaseHibernateDAO的save方法进行了测试。
这个代码貌似没错,但是在运行的时候抛出了如下错误:
Exception in thread "main" org.hibernate.SessionException: Session is closed!
at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:49)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:526)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:518)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:514)
at com.linbs.core.common.hibernate.BaseHibernateDAO.save(BaseHibernateDAO.java:31)
at com.linbs.core.common.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e.CGLIB$save$3(<generated>)
at com.linbs.core.common.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e$$FastClassByCGLIB$$e5947bbb.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:167)
at com.test.TransactionDAOProxy.intercept(TransactionDAOProxy.java:49)
at com.linbs.core.common.hibernate.BaseHibernateDAO$$EnhancerByCGLIB$$c88d447e.save(<generated>)
at com.test.Test.main(Test.java:21)

为什么? 经过测试,以及朋友的提醒,发现在BaseHibernateDAO的save()方法里调用了getSession()方法,而在运行的时候CGLIB会对getSession()和save()这2个方法都进行代理,因此在对save()进行tx.commit()和session.flush();的时候,在getSession()方法中已经进行了事务管理并关闭了session。

唉!一不小心就踏入了陷阱。




1
0
分享到:
评论

相关推荐

    Cglib3.3.0最新版jar包

    Cglib就是一种实现动态代理的方式,不同于JDK自带的Proxy,Cglib不需要目标对象实现任何接口,因此可以用于不能实现接口的对象。通过Enhancer类,我们可以指定需要代理的目标类,并提供回调方法实现动态代理逻辑。 ...

    cglib.jar下载

    CGLIB介绍与原理(部分节选自网络) 一、什么是CGLIB?...cglib-nodep-2.2.jar:使用nodep包不需要关联asm的jar包,jar包内部包含asm的类. cglib-2.2.jar:使用此jar包需要关联asm的jar包,否则运行时报错.

    CGLIB依赖jar包

    1. `cglib-nodep-2.2.jar`:这是CGLIB的主要库,包含了CGLIB的所有功能,但是不依赖于其他的外部库,比如ASM。如果你的项目中已经包含了ASM,或者不需要直接使用ASM,可以选择这个版本。 2. `cglib-2.2.jar`:这个...

    cglib_cglib3.2_remain3gr_cglibjar包_cglib.jar_

    【CGLib:强大的Java代码生成库】 CGLib(Code Generation Library)是一个强大的、高性能的代码生成库,它在运行期扩展Java类与实现Java接口。这个库最初是为EJB的透明代理而设计的,但后来发展成为了一个广泛的...

    cglib的依赖包

    - 对于final类和final方法,CGlib无法生成子类进行增强,因为Java不支持final类的子类化。 - 使用CGlib可能会导致内存占用增加,因为它需要创建额外的子类对象。 - 如果目标类的构造函数有参数,使用CGlib时需要...

    cglib_cglib.zip

    在Spring中,如果你选择使用基于代理的事务管理,且目标类不实现接口,Spring就会默认使用CGLib来创建代理。通过代理,可以在方法调用前后插入额外的逻辑,如事务控制、性能监控等。 CGLib的使用通常涉及到以下几个...

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

    1. `cglib-nodep-2.1_3.jar`:这是CGLib的核心库,不依赖于任何外部库,包括ASM。它包含了创建代理对象和动态子类所需的所有类和方法。 2. `asm-util-2.2.3.jar`:ASM的工具库,包含了一些实用工具,如类分析器、类...

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

    CGLIB-nodep-2.2.jar是CGLIB的一个无依赖版本,"nodep"即"no dependency"的缩写,意味着这个版本的CGLIB不包含任何外部依赖,只包含了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包及依赖汉cglib3.1和asm4.2

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

    cglib2.2jar包

    1. CGLIB不能对final类或final方法进行代理,因为无法生成这些类或方法的子类。 2. 代理对象的创建会带来一定的内存和性能开销,因此在不需要代理时,应及时释放代理对象。 总之,CGLIB作为一个强大的字节码生成库...

    cglib必需的包

    这个文件是CGlib的主要实现包,不依赖于任何其他的外部库,因此被称为“nodep”(无依赖)。它包含了创建子类并进行方法拦截的核心功能,使得我们可以为一个类创建代理,即使这个类没有实现接口。CGlib通过字节码...

    CGLib3.2.5依赖包及源码

    前者是CGLib的核心库,后者是独立版,不依赖于ASM库,适用于那些不希望引入额外依赖的项目。ASM是一个底层的Java字节码操作和分析框架,用于动态生成类和接口的实例。 源码包提供了CGLib的实现细节,包括`cglib-...

    cglib必须导入的包和案例

    Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展. JDK的动态代理有一个限制,就是使用...不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉.

    cglib所有jar包

    总的来说,CGlib是Java开发中不可或缺的工具之一,它提供了强大的代码生成能力,使得开发者可以更加灵活地扩展和增强已有代码,提高代码的复用性和可维护性。这个"cglib所有jar包"资源对于进行Java开发的程序员来说...

    cglib.jar以及cglib-src.jar

    CGLib,全称为Code Generation Library,是一个强大的高性能的代码生成库,它在Java世界中被广泛应用,尤其是在动态代理和AOP(面向切面编程)领域。CGLIB是由Evan Schoolnik开发并维护的,它最初是作为Jakarta OGNL...

    Cglib的jar文件 Cglib.zip

    Cglib是一个强大的Java代码生成库,它在运行时动态创建子类,为现有类提供扩展功能。这个库被广泛用于实现AOP(面向切面编程)中的代理机制,特别是当无法通过接口代理时,例如Java标准库中的类。Cglib是Eclipse的...

    cglib.jar | asm.jar对应版本

    当一个类没有接口或者为了性能考虑不希望使用接口时,cglib就显得尤为重要。 cglib的核心类是`Enhancer`,它提供了创建代理对象的入口。通过调用`Enhancer.create()`方法,我们可以为指定的类创建一个代理对象,并...

Global site tag (gtag.js) - Google Analytics