目录
前言:
在使用Springboot的过程中,由于Springboot为我们做了大量的初始化配置工作,所以我们在使用的时候只需要进行少许的配置就能达到我们想要的目的, 但是也正因为如此,对于很多不了解其中原委的同学而言一旦配置有问题或者确实配置而报错,从何处开始排查问题便成为了一个困难,甚至当业务需求要求打破springboot的默认配置的时候时候,我们自定义的配置应该如何进行也会难到一部分同学,例如自定义多个数据源。
本文沿着Springboot的配置梳理其对jpa的配置,以便后期关于jpa的地方出问题时知道从何处开始排查问题。
HibernateJpaAutoConfiguration
提示:几乎所有的Springboot应用的初始化都可以从autoconfigure这个包开始查起。
所以我们先来看下auto包下面的东西:
从图中我们找到了HibernateJpaAutoConfiguration. 话不都说,直接上代码:
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class, SessionImplementor.class })
@EnableConfigurationProperties(JpaProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
@Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {
}
说明:
1.当SpringJpa以及JPA规范相应的类存在的情况下才进行自动配置。
2.引入JpaProperties (所以需要jpa的自定义配置就可以看这个类)
3.在数据源初始化完成后再进行配置
4.引入Hibernate实现的配置 HibernateJpaConfiguration(hibernate应该算是JPA事实上的标准实现,当年大佬们制定JPA规范的时候是反过来参考Hibernate的)
其它的都比较简单,这里直接看HibernateJpaConfiguration的实现配置:HibernateJpaConfiguration
HibernateJpaConfiguration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(HibernateProperties.class)
@ConditionalOnSingleCandidate(DataSource.class)
class HibernateJpaConfiguration extends JpaBaseConfiguration {
}
还是先看类的结构,首先是引入HibernateProperties,这个配置是针对Hibernate实现的特殊配置,它与刚才提到的JpaProperties构成了我们整个应用的关于ORM的配置。例如是否显示sql,是否自动DDL。
@ConditionalOnSingleCandidate(DataSource.class) 已经实例化DataSource,并且只有一个可选项。
其次它还继承了JpaBaseConfiguration(JPA的一些基础配置),所以这里除了它自身hibernate的配置之外还有jpa的配置。
还是先看hibernate的实现,上代码:
首先是初始化:
HibernateJpaConfiguration(DataSource dataSource, JpaProperties jpaProperties,
ConfigurableListableBeanFactory beanFactory, ObjectProvider<JtaTransactionManager> jtaTransactionManager,
HibernateProperties hibernateProperties,
ObjectProvider<Collection<DataSourcePoolMetadataProvider>> metadataProviders,
ObjectProvider<SchemaManagementProvider> providers,
ObjectProvider<PhysicalNamingStrategy> physicalNamingStrategy,
ObjectProvider<ImplicitNamingStrategy> implicitNamingStrategy,
ObjectProvider<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
super(dataSource, jpaProperties, jtaTransactionManager);
this.hibernateProperties = hibernateProperties;
this.defaultDdlAutoProvider = new HibernateDefaultDdlAutoProvider(providers);
this.poolMetadataProvider = new CompositeDataSourcePoolMetadataProvider(metadataProviders.getIfAvailable());
this.hibernatePropertiesCustomizers = determineHibernatePropertiesCustomizers(
physicalNamingStrategy.getIfAvailable(), implicitNamingStrategy.getIfAvailable(), beanFactory,
hibernatePropertiesCustomizers.orderedStream().collect(Collectors.toList()));
}
private List<HibernatePropertiesCustomizer> determineHibernatePropertiesCustomizers(
PhysicalNamingStrategy physicalNamingStrategy, ImplicitNamingStrategy implicitNamingStrategy,
ConfigurableListableBeanFactory beanFactory,
List<HibernatePropertiesCustomizer> hibernatePropertiesCustomizers) {
List<HibernatePropertiesCustomizer> customizers = new ArrayList<>();
if (ClassUtils.isPresent("org.hibernate.resource.beans.container.spi.BeanContainer",
getClass().getClassLoader())) {
customizers.add((properties) -> properties.put(AvailableSettings.BEAN_CONTAINER,
new SpringBeanContainer(beanFactory)));
}
if (physicalNamingStrategy != null || implicitNamingStrategy != null) {
customizers.add(
new NamingStrategiesHibernatePropertiesCustomizer(physicalNamingStrategy, implicitNamingStrategy));
}
customizers.addAll(hibernatePropertiesCustomizers);
return customizers;
}
这里会初始化HibernateProperties、HibernateDefaultDdlAutoProvider、CompositeDataSourcePoolMetadataProvider、hibernatePropertiesCustomizers;其中hibernatePropertiesCustomizers包括了手动设置的BeanContainer(spring的具体实现,为hibernate提供容器IOC的能力),还有xxxxNamingStrategy,用于将domain对象的注解与数据库字段对应上。
HibernateJpaConfiguration 继承至JpaBaseConfiguration
JpaBaseConfiguration
该类主要初始化Jpa规范中的核心“接口”,包括:TransactionManager、JpaVendorAdapter、LocalContainerEntityManagerFactoryBean(EntityManager),如果开启了openSessionInView(配置文件中配置spring.jpa.open-in-view=true),则还会初始化OpenEntityManagerInViewInterceptor这个拦截器然后配置到Controller的拦截中。
DataSourceInitializedPublisher
这个类从注释可以看出是用于ORM框架自动DDL的,它是在初始化JpaBaseConfiguration的时候@Import进去的,同时它也是一个bean后置处理器。
后续会对事务、实体管理器、openSessionInView、自动DDL等进行一一详细的讲解