2、Spring的LocalSessionFactoryBean創建過程源碼分析


 

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相同的配置效果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM