在hibernate 类ThreadLocalSessionContext中有两段source code
public final Session currentSession(); throws HibernateException {
Session current = existingSession( factory );;
if (current == null); {
current = buildOrObtainSession();;
// register a cleanup synch
current.getTransaction();.registerSynchronization( buildCleanupSynch(); );;
// wrap the session in the transaction-protection proxy
if ( needsWrapping( current ); ); {
current = wrap( current );;
}
// then bind it
doBind( current, factory );;
}
return current;
}
private boolean needsWrapping(Session session); {
// try to make sure we don't wrap and already wrapped session
return session != null
&& ! Proxy.isProxyClass( session.getClass(); );
|| ( Proxy.getInvocationHandler( session ); != null
&& ! ( Proxy.getInvocationHandler( session ); instanceof TransactionProtectionWrapper ); );;
}
session != null
&& ! Proxy.isProxyClass( session.getClass() )
就是说session不为空,并且没有增加过proxy.
( Proxy.getInvocationHandler( session ) != null
&& ! ( Proxy.getInvocationHandler( session ) instanceof TransactionProtectionWrapper ) );就是说已经增加过proxy,但不是TransactionProtectionWrapper ,那么TransactionProtectionWrapper 是什么东东呢?
请看它的invoke方法:
public Object invoke(Object proxy, Method method, Object[] args); throws Throwable {
try {
// If close(); is called, guarantee unbind();
if ( "close".equals( method.getName();); ); {
unbind( realSession.getSessionFactory(); );;
}
else if ( "toString".equals( method.getName(); );
|| "equals".equals( method.getName(); );
|| "hashCode".equals( method.getName(); );
|| "getStatistics".equals( method.getName(); );
|| "isOpen".equals( method.getName(); ); ); {
// allow these to go through the the real session no matter what
}
else if ( !realSession.isOpen(); ); {
// essentially, if the real session is closed allow any
// method call to pass through since the real session
// will complain by throwing an appropriate exception;
// NOTE that allowing close(); above has the same basic effect,
// but we capture that there simply to perform the unbind...
}
else if ( !realSession.getTransaction();.isActive(); ); {
// limit the methods available if no transaction is active
if ( "beginTransaction".equals( method.getName(); );
|| "getTransaction".equals( method.getName(); );
|| "isTransactionInProgress".equals( method.getName(); );
|| "setFlushMode".equals( method.getName(); );
|| "getSessionFactory".equals( method.getName(); ); ); {
log.trace( "allowing method [" + method.getName(); + "] in non-transacted context" );;
}
else if ( "reconnect".equals( method.getName(); );
|| "disconnect".equals( method.getName(); ); ); {
// allow these (deprecated); methods to pass through
}
else {
throw new HibernateException( method.getName(); + " is not valid without active transaction" );;
}
}
log.trace( "allowing proxied method [" + method.getName(); + "] to proceed to real session" );;
return method.invoke( realSession, args );;
}
catch ( InvocationTargetException e ); {
if ( e.getTargetException(); instanceof RuntimeException ); {
throw ( RuntimeException ); e.getTargetException();;
}
else {
throw e;
}
}
}
就是说它对session调用的方法做了一些限制。
分享到:
相关推荐
- **难以调试**:由于ThreadLocal的隐式性,有时可能会导致难以发现的问题,特别是当线程池中的线程复用时。 ### 4. 使用注意事项 - 使用完毕后,应调用`remove()`方法清除ThreadLocal变量,防止内存泄漏。 - 尽量...
2. 请求上下文:在Web应用中,可以使用ThreadLocal保存请求相关的数据,如用户信息、事务ID等,方便在处理请求的整个生命周期内访问。 3. 线程安全的配置对象:为每个线程提供独立的配置参数,避免线程间冲突。 ...
**ThreadLocal的使用** ThreadLocal的使用非常简单,主要包括以下几个步骤: 1. 创建ThreadLocal实例:首先,你需要创建一个ThreadLocal实例,这将作为线程局部变量的模板。 2. 设置值:使用`set(T value)`方法为...
使用 ThreadLocal 可以避免在多线程环境下频繁使用锁来保证线程安全,提高了性能。 ThreadLocal 的常见应用场景包括: 1. **线程本地事务**:银行交易系统中,每个线程维护自己的事务状态,避免了事务的同步问题。...
在 ThreadLocal 的源码中,我们可以发现,并没有存储变量的字段值。ThreadLocal 并不负责保存变量,而是通过 get() 方法来获取当前线程的副本值。initialValue() 方法用于设置默认初始值,而 get() 方法则用于获取...
在这个例子中,我们可以发现有一个UserContext的静态类,它使用ThreadLocal来保存用户的登录信息。这个类提供了get和clear方法来获取和清理用户的登录信息。 在拦截器中,我们可以发现调用了UserContext.set方法来...
在Java并发编程中,ThreadLocal是一个非常重要的工具类,它提供了一种线程内部的存储方式,可以为...在实际应用中,正确使用ThreadLocal以及理解ThreadLocalMap的内部实现细节对于避免内存泄漏和提高程序性能至关重要。
它为开发者提供了在分布式系统(如配置管理、服务发现、断路器、负载均衡、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等)中快速构建一些常见模式的能力。 Eureka是Spring ...
- **定义**:内存泄露是指不再使用的对象仍然占据内存空间,且无法通过垃圾回收机制释放,导致可用内存逐渐减少直至耗尽。 - **识别**:通过 MAT 工具的 `Leak Suspects` 功能,可以识别出潜在的内存泄露源头。 - **...
18. **避免使用ThreadLocal**:虽然方便,但可能导致内存泄漏,应谨慎使用。 19. **资源关闭**:使用try-with-resources语句自动关闭流和其他可关闭资源。 20. **避免使用浮点运算比较**:由于浮点精度问题,不...
如果发现`ThreadLocal`绑定的`Dao`类占用了大量内存,则需要进一步检查此类是否合理使用了`ThreadLocal`机制。通常情况下,不当使用`ThreadLocal`会导致每个线程保留大量不必要的数据,从而增加内存负担。 ##### 2....
当发现中断请求时,根据业务逻辑决定如何响应。一种常见的做法是抛出`InterruptedException`,或者取消任务执行,清理资源。 **4. LockSupport.park()和unpark()与object.wait()和notify()的区别** `LockSupport....
4. **并发编程**:讲解Java并发API的正确使用,如synchronized、volatile、ThreadLocal、Lock接口等,以及并发工具类如ExecutorService、CountDownLatch、CyclicBarrier等。 5. **集合框架**:深入理解List、Set、...
11. **避免使用ThreadLocal**:ThreadLocal会占用线程栈空间,过多使用可能导致内存泄漏。 12. **减少循环内部的I/O操作**:将I/O操作移出循环,降低循环开销。 13. **优化异常处理**:异常处理不应成为性能瓶颈,...
2. **利用工具定位并修复**:借助于前面提到的诊断工具,定位到具体的内存泄露源,并针对性地修改代码,比如清理不再使用的对象引用,合理使用各种类型的引用,以及正确管理ThreadLocal变量。 3. **定期进行系统...
2. 避免线程同步:尽可能使用`ThreadLocal`减少线程间的数据共享,提高性能。 3. 死锁预防:避免多个线程持有对方需要的锁,导致死锁。 五、IO与NIO 1. 文件操作:避免使用`FileInputStream/FileOutputStream`,...
此外,提倡使用volatile关键字确保变量可见性,以及使用`ThreadLocal`来解决线程局部变量问题。 4. **日志记录**:日志是系统调试和故障排查的重要手段。手册建议根据日志级别(DEBUG、INFO、WARN、ERROR)进行适当...
7. **并发编程**:掌握synchronized、volatile、ThreadLocal等并发工具的使用,遵循线程安全的最佳实践,避免死锁、活锁和饥饿现象。 8. **性能优化**:合理使用数据结构和算法,避免过度优化,使用StringBuilder...
4. **并发编程**:合理使用synchronized、volatile、ThreadLocal等关键字,避免并发问题。推荐使用并发工具类,如ConcurrentHashMap、CountDownLatch等。 5. **日志记录**:统一使用SLF4J日志门面,结合具体日志...