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
中獲取的實際上是FactoryBean
的getObject()
返回的物件,而不是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();
}
}