2、Spring的LocalSessionFactoryBean创建过程源码分析

时间:2022-01-04 07:51:29

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