1:定义
LocalSessionFactoryBean 类主要作用是把hibernate的SessionFactory纳入到spring的容器中,由spring来管理SessionFactory,我们也可以依赖注入sessionFactory。
2:继承关系
LocalSessionFactoryBean 继承了HibernateExceptionTranslator类,实现了FactoryBean<SessionFactory>, ResourceLoaderAware, InitializingBean, DisposableBean类。
- HibernateExceptionTranslator:负责转换hibernate异常(HibernateException)为spring异常体系(DataAccessException )
- FactoryBean:对普通的spring bean进行封装,类中getObject方法是返回被封装的bean。
- ResourceLoaderAware:当实现了
ResourceLoaderAware
接口的类部署到application context(比如受Spring管理的bean)中时,它会被application context识别为ResourceLoaderAware
。 接着application context会调用setResourceLoader(ResourceLoader)
方法,并把自身作为参数传入该方法(记住,所有Spring里的application context都实现了ResourceLoader
接口)。 - InitializingBean:实现该接口的bean,spring会在初始化bean时调用InitializingBean接口里的afterPropertiesSet方法。
- DisposableBean:在bean被销毁时调用destroy方法
3:功能
既然LocalSessionFactoryBean 类主要作用是把hibernate的SessionFactory纳入到spring的容器中,那么hibernate的SessionFactory肯定也在这个类中初始化那么在哪初始化呢,上面讲到LocalSessionFactoryBean 实现 了InitializingBean接口,spring初始化这个bean时调用了afterPropertiesSet方法
下面是源代码afterPropertiesSet的实现:
public void afterPropertiesSet() throws IOException {
LocalSessionFactoryBuilder sfb = new LocalSessionFactoryBuilder(this.dataSource, this.resourcePatternResolver);
if (this.configLocations != null) {
for (Resource resource : this.configLocations) {
// Load Hibernate configuration from given location.
sfb.configure(resource.getURL());
}
}
if (this.mappingResources != null) {
// Register given Hibernate mapping definitions, contained in resource files.
for (String mapping : this.mappingResources) {
Resource mr = new ClassPathResource(mapping.trim(), this.resourcePatternResolver.getClassLoader());
sfb.addInputStream(mr.getInputStream());
}
}
if (this.mappingLocations != null) {
// Register given Hibernate mapping definitions, contained in resource files.
for (Resource resource : this.mappingLocations) {
sfb.addInputStream(resource.getInputStream());
}
}
if (this.cacheableMappingLocations != null) {
// Register given cacheable Hibernate mapping definitions, read from the file system.
for (Resource resource : this.cacheableMappingLocations) {
sfb.addCacheableFile(resource.getFile());
}
}
if (this.mappingJarLocations != null) {
// Register given Hibernate mapping definitions, contained in jar files.
for (Resource resource : this.mappingJarLocations) {
sfb.addJar(resource.getFile());
}
}
if (this.mappingDirectoryLocations != null) {
// Register all Hibernate mapping definitions in the given directories.
for (Resource resource : this.mappingDirectoryLocations) {
File file = resource.getFile();
if (!file.isDirectory()) {
throw new IllegalArgumentException(
"Mapping directory location [" + resource + "] does not denote a directory");
}
sfb.addDirectory(file);
}
}
if (this.entityInterceptor != null) {
sfb.setInterceptor(this.entityInterceptor);
}
if (this.namingStrategy != null) {
sfb.setNamingStrategy(this.namingStrategy);
}
if (this.hibernateProperties != null) {
sfb.addProperties(this.hibernateProperties);
}
if (this.annotatedClasses != null) {
sfb.addAnnotatedClasses(this.annotatedClasses);
}
if (this.annotatedPackages != null) {
sfb.addPackages(this.annotatedPackages);
}
if (this.packagesToScan != null) {
sfb.scanPackages(this.packagesToScan);
}
if (this.jtaTransactionManager != null) {
sfb.setJtaTransactionManager(this.jtaTransactionManager);
}
// Build SessionFactory instance.
this.configuration = sfb;
this.sessionFactory = buildSessionFactory(sfb);
}
方法一开始就新建了LocalSessionFactoryBuilder对象,这个对象一看名字就知道就是生成SessionFactory用的,他直接继承了hibernate的Configuration类,在hibernate中Configuration就是来生成SessionFactory的,中间代码都是在配置环境,hibernate配置文件路径,注解类路径等等,最后调用了buildSessionFactory(sfb);方法,其实这个方法里面就是调用了sfb.buildSessionFactory();那为什么不直接调用呢反而多此一举的感觉,其实这个方法目的就是留个口子,用户可以覆盖此方法定制自己的SessionFactory初始化。继续看sfb.buildSessionFactory()方法,
public SessionFactory buildSessionFactory() throws HibernateException {
ClassLoader appClassLoader = (ClassLoader) getProperties().get(AvailableSettings.APP_CLASSLOADER);
Thread currentThread = Thread.currentThread();
ClassLoader threadContextClassLoader = currentThread.getContextClassLoader();
boolean overrideClassLoader =
(appClassLoader != null && !appClassLoader.equals(threadContextClassLoader));
if (overrideClassLoader) {
currentThread.setContextClassLoader(appClassLoader);
}
try {
return super.buildSessionFactory();
}
finally {
if (overrideClassLoader) {
currentThread.setContextClassLoader(threadContextClassLoader);
}
}
}
开始做了一些出来确保当前类加载器就是应用类加载器,然后调用了super.buildSessionFactory();方法,开始说过LocalSessionFactoryBuilder是继承Configuration的,现在它直接调用了父类的buildSessionFactory()也就是交给hibernate的Configuration来初始化了整个加载过程就是这样子。