先声明下,本人系菜鸟一个,问的问题如果类似于1+1为什么等于2,请少拍板
这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;
}
}
其中的HibernateUtil类的getSession()方法是一个从线程中取得session副本的函数,代码相信各位大牛已经很熟悉,在此就不贴出来了。
测试类如下:
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);
}
}
其中的baseDAO.save(user);函数代码如下:
/**
* 取得当期进程的session对象
* @return
*/
public Session getSession() {
return HibernateUtil.getSession();
}/** * 保存一个新的实体类的实例,并返回标识号 * @param obj * @return */ public Serializable save(final Object obj) { return this.getSession().save(obj); }
测试类运行的时候报出了如下错误:
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)
通过debug发现session = HibernateUtil.getSession();和result = proxy.invokeSuper(obj, args);中调用的session不属于同一个对象。而session是在线程中取得的,可见session = HibernateUtil.getSession();和result = proxy.invokeSuper(obj, args);不是在同一个线程中运行的。于是猜想:cglib在运行中动态创建类而新创建的类和原来创建的类是不在同一线程中运行的,不知道我的猜想是不是正确,请各位大牛指教!!