乐鱼电竞

    教育行业A股IPO第一股(股票代码 003032)

    全国咨询/投诉热线:400-618-4000

    Hibernate中如何获取与线程绑定的session源码解析

    更新时间:2018年12月19日15时02分 来源:乐鱼播客 浏览次数:

    深入了解下ThreadLocalSessionContext如何做到将session和thread进行绑定.
         
    首先,先来看下关键性的源码
          
    而currentSessionContext对象又是在SessionFactoryImpl的构造方法中初始化的
    [Java] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    public final class SessionFactoryImpl implements SessionFactoryImplementor{
        private final transient CurrentSessionContext currentSessionContext;
        public SessionFactoryImpl(final MetadataImplementor metadata, SessionFactoryOptions options) {
            LOG.debug( "Building session factory" );
            
            ...省略大量代码
            currentSessionContext = buildCurrentSessionContext();
            ...省略大量代码
        }
    }
          
    所以我们在这个buildCurrentSessionContext()方法中发现
          
    好了~关键定位到了接下来我们就开始通过ThreadLocalSessionContext对象的创建开始,首先是执行的构造方法
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    public ThreadLocalSessionContext(SessionFactoryImplementor factory) {
        super( factory );
    }
          
    查看父类AbstractCurrentSessionContext构造
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    public abstract class AbstractCurrentSessionContext implements CurrentSessionContext {
        private final SessionFactoryImplementor factory;
        protected AbstractCurrentSessionContext(SessionFactoryImplementor factory) {
            this.factory = factory;
        }
        .....
    }
          
    看到这里发现只是进行对象的保存操作而已~
          
    回归ThreadLocalSessionContext
          
    当然,开始分析流程吧~
          
    Session current = existingSession( factory() );
          
    第一眼看到的factory()源头
    [Java] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    public abstract class AbstractCurrentSessionContext implements CurrentSessionContext {
        private final SessionFactoryImplementor factory;
        protected AbstractCurrentSessionContext(SessionFactoryImplementor factory) {
            this.factory = factory;
        }
        public SessionFactoryImplementor factory() {
            return factory;
        }
    ....
    }
          
    由此可出这个就是我们之前创建对象时通过构造传入的对象,接下来开始分析existingSession()方法
    [Java] 纯文本查看 复制代码
    ?
    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    private static Session existingSession(SessionFactory factory) {
        final Map sessionMap = sessionMap();
        if ( sessionMap == null ) {
            return null;
        }
        return (Session) sessionMap.get( factory );
    }
    protected static Map sessionMap() {
        return CONTEXT_TL.get();
    }
          
    通过上面的源码我们分析出来核心在CONTEXT_TL对象,继续去找这个对象是什么时候创建的,最后发现是在类加载的时候就会创建
    [Java] 纯文本查看 复制代码
    ?
    1
    private static final ThreadLocal<Map> CONTEXT_TL = new ThreadLocal<Map>();
          
    ok~由此我们发现了这里其实使用的是ThreadLocal,这个是什么东西呢?将网上现成的解释直接拉过来了~~回头再开个章节单独细讲吧~
    什么是ThreadLocal
    ThreadLocal是一个本地线程副本变量工具类。主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰,在高并发场景下,可以实现无状态的调用,特别适用于各个线程依赖不通的变量值完成操作的场景。
         
    由此可知threadlocal可以为每个线程单独保存数据和获取互不影响~
          
    而我们这里在当前线程中保存的是一个Map,这个Map又是什么呢?慢慢来~还是继续往下分析
          
          
    第一次访问的话肯定什么都不存在,所以sessionMap一定为null,执行到最后,我们看到了doBind( current, factory() );
    [Java] 纯文本查看 复制代码
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    private static void doBind(org.hibernate.Session session, SessionFactory factory) {
        Map sessionMap = sessionMap();
        if ( sessionMap == null ) {
            sessionMap = new HashMap();
            CONTEXT_TL.set( sessionMap );
        }
        sessionMap.put( factory, session );
    }
          
    这doBind方法中,我们发现了又调用sessionMap()方法,这个方法我们也看过了,直接从ThreadLocal中获取,但是我们没存过又怎么能获取到呢?对吧,所以此时又会进入到为null的逻辑判断中,在这里我们总算是发现,我们在这创建了一个HashMap,并且把当前的hashMap保存到了CONTEXT_TL对象中,这样就保证了当前的map和当前线程进行绑定了~而做完这个操作后,我们又把传进来的factory和我们创建的session对象又保存到了我们的Map中,从而保证了通过我们的线程能够找到对应的map,而通过当前线程获取到的map,我们又找到了对应当前factory对应的session,从而实现了线程和当前数据库会话进行了绑定~


    作者:乐鱼播客JavaEE培训学院

    首发:http://java.itcast.cn

    0 分享到:
    和我们在线交谈!
    【网站地图】【sitemap】