spring的LocalSessionFactoryBean生成過程與hibernate的SessionFactory生成過程是高度吻合的。
為了后面源碼分析,首先講解一個接口,一個類的功能:
①、接口InitializingBean
接口的功能:這個接口專門為bean設計的,它只有一個方法。我們知道所有的bean都是由beanFactory來生成的,如果一個bean實現了該接口,在beanFactory為該bean裝配好了所有的屬性以后,在返回實際bean之前還會調用一次該接口的afterPropertiesSet(...)方法。其設計目的是為了實現個性化,或者是為了檢查bean屬性值的完整性等。
public interface InitializingBean { void afterPropertiesSet() throws Exception; }
②、類LocalSessionFactoryBuilder
顯然,LocalSessionFactoryBuilder繼承自org.hibernate.cfg.Configuration,那么Configuration擁有的屬性,LocalSessionFactoryBuilder也具有
public class LocalSessionFactoryBuilder extends Configuration{ //... }
從LocalSessionFactoryBean源碼中分析出其於hibernate的sessionFactory和configuration之間的關系:
public interface InitializingBean { void afterPropertiesSet() throws Exception; } //②、類LocalSessionFactoryBuilder //顯然,LocalSessionFactoryBuilder繼承自org.hibernate.cfg.Configuration,那么Configuration擁有的屬性,LocalSessionFactoryBuilder也具有 public class LocalSessionFactoryBuilder extends Configuration{ //... } //現在主要分析LocalSessionFactoryBean //1、看一下幾個非常重要的屬性值定義 public class LocalSessionFactoryBean extends... implements InitializingBean, ...{ //數據源 private DataSource dataSource; //hibernate的配置文件Xxx.cfg.xml所在的 //位置多個可以用","隔開 private Resource[] configLocations; private String[] mappingResources; //hibernate的映射文件位置 private Resource[] mappingLocations; //hibernate的properties屬性,存放了配置 //文件中解析property標簽的結果 private Properties hibernateProperties; //hibernate的configuration屬性 private Configuration configuration; //這個sessionfactory是hibernate的sessionFactory private SessionFactory sessionFactory; //省略其它的屬性以及setter方法... //注意這個set方法,說明當只有一個配置文件 //的時候可以使用configLocation屬性來配置, //最終也會被轉換成configLocations public void setConfigLocation(Resource configLocation) { this.configLocations = new Resource[] {configLocation}; } @Override public void afterPropertiesSet() throws IOException { LocalSessionFactoryBuilder sfb = new LocalSessionFactoryBuilder(this.dataSource, this.resourcePatternResolver); if (this.configLocations != null) { for (Resource resource : this.configLocations) { //sfb.configure(...)實際上也就是調用其父類 //org.hibernate.cfg.Configuration的configure(...)方法 //這里完成xxx.cfg.xml文件中property節點 //的解析,得到一個properties sfb.configure(resource.getURL()); } } //mappingResources和mappingLocations效果是一樣的, //都會將資源轉換成輸入流,並調用sfb.addInputStream(...)方法 //sfb.addInputStream(...)最終會完成xxx.cfg.xml文件的 //非property節點解析(主要有3類:mapping、class-cache和collection-cache) //將解析結果放入到metadataSourceQueue中 if (this.mappingResources != null) { for (String mapping : this.mappingResources) { Resource mr = new ClassPathResource(mapping.trim(), this.resourcePatternResolver.getClassLoader()); sfb.addInputStream(mr.getInputStream()); } } if (this.mappingLocations != null) { for (Resource resource : this.mappingLocations) { sfb.addInputStream(resource.getInputStream()); } } //sfb.addProperties(...)方法會調用properties.putAll( extraProperties )方法 //說明我們可以配置一個properties對象來達到配置xxx.cfg.xml相同的效果!! //兩方面的配置最終都會放入到properties對象中 if (this.hibernateProperties != null) { sfb.addProperties(this.hibernateProperties); } //省略若干其它方法... // 將sfb向上轉型,LocalSessionFactoryBean中的configuration屬性實際上 // 就是org.hibernate.cfg.Configuration this.configuration = sfb; //在得到configuration以后,通過它來創建一個sessionFactory, //並賦值給sessionFactory屬性(LocalSessionFactoryBean的屬性) //在底層會調用return super.buildSessionFactory()來的到一個 //sessionFactory,由於其父類是org.hibernate.cfg.Configuration //所以,相當於調用了configuration.buildSessionFactory()來生成 //sessionFactory,這是hibernate4.0版本之前的做法,新版本已經 //被buildSessionFactory(ServiceRegistry)所取代。 this.sessionFactory = buildSessionFactory(sfb); } }
總結spring的LocalSessionFactoryBean實際完成的工作有:
1、通過解析bean中的configLocation和mappingLocations等屬性,得到一個hibernate的原生態的org.hibernate.cfg.Configuration屬性
2、通過org.hibernate.cfg.Configuration生成一個hibernate原生態的org.hibernate.SessionFactory屬性
3、可以在外部配置一個Properties對象,並將其配置為properties屬性,可以達到與xxx.cfg.xml相同的配置效果