1. 程式人生 > >spring 自動注入Hibernate中的SessionFactory 探索

spring 自動注入Hibernate中的SessionFactory 探索

之前用Spring的註解模式配置Hibernate的時候覺得很簡單。

使用@autowire 自動注入

 @Autowired
 private SessionFactory sessionFactory;

然後在方法中直接使用

Session session = sessionFactory.getCurrentSession()

但是,後來看原始碼的時候卻有了疑問。

在XML配置檔案中, bean 的配置裡面 SessionFactory 對映的 類檔案是org.springframework.orm.hibernate4.LocalSessionFactoryBean

<bean id="sessionFactory"  class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

然而開啟 LocalSessionFactoryBean 類中的程式碼,卻沒有發現getCurrentSession()這個方法。

後來查詢資料才發現真正的原因。

LocalSessionFactoryBean 實現了 介面 FactoryBean,FactoryBean中有一個方法 : getObject()

根據Bean的Id, 從BeanFactory中獲取的實際上是FactoryBeangetObject()返回的物件,而不是FactoryBean本身。

LocalSessionFactoryBean中我們看到getObject()方法的具體實現如下:

    @Override
    public SessionFactory getObject() {
        return this.sessionFactory;
    }

它直接返回了一個sessionFactory物件。
現在問題又來了,sessionFactory實際上也是一個介面,那麼它的具體實現是在什麼地方呢?

我們又看到 LocalSessionFactoryBean 還實現了另外一個介面InitializingBean,顧名思義,這個介面就是提供獲得Bean時候的初始化操作用的。

這個介面只定義了一個方法:

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}

LocalSessionFactoryBean 對這個方法的具體實現有很多程式碼,我只擷取最關鍵的程式碼如下:

        // Build SessionFactory instance.
        this.configuration = sfb;
        this.sessionFactory = buildSessionFactory(sfb);

可見 sessionFactory成員的裝配,是因為使用了buildSessionFactory(sfb)方法。

這個sfb 變數是什麼呢?

LocalSessionFactoryBuilder sfb = new LocalSessionFactoryBuilder(this.dataSource, this.resourcePatternResolver);

可以看到sfb讀取了資料庫的配置資訊

buildSessionFactory方法做了什麼事情呢?

這個方法下面有多層封裝,層層往下,最關鍵的程式碼是···Configuration中的···buildSessionFactory()方法,其具體程式碼如下:

    public SessionFactory buildSessionFactory(ServiceRegistry serviceRegistry) throws HibernateException {
        LOG.debugf("Preparing to build session factory with filters : %s", this.filterDefinitions);
        this.buildTypeRegistrations(serviceRegistry);
        this.secondPassCompile();
        if(!this.metadataSourceQueue.isEmpty()) {
            LOG.incompleteMappingMetadataCacheProcessing();
        }

        this.validate();
        Environment.verifyProperties(this.properties);
        Properties copy = new Properties();
        copy.putAll(this.properties);
        ConfigurationHelper.resolvePlaceHolders(copy);
        Settings settings = this.buildSettings(copy, serviceRegistry);
        return new SessionFactoryImpl(this, this.mapping, serviceRegistry, settings, this.sessionFactoryObserver);
    }

可以看到,在這個程式碼中,最後的 new SessionFactoryImpl...才是SessionFactory介面的真正實現。

最後的真正實現getCurrentSession()的程式碼如下:

    public Session getCurrentSession() throws HibernateException {
        if(this.currentSessionContext == null) {
            throw new HibernateException("No CurrentSessionContext configured!");
        } else {
            return this.currentSessionContext.currentSession();
        }
    }