概述
JpaBaseConfiguration
是Spring Boot
提供的对JPA
进行配置的抽象基类。针对不同的JPA
实现,会有不同的具体实现类。比如Spring Boot
内置支持基于Hibernate
的JPA
,所以它提供了相应的实现HibernateJpaConfiguration
。而如果开发人员想使用其他JPA
实现,比如EclipseLink
或者OpenJPA
,就要继承JpaBaseConfiguration
提供相应的具体实现。
虽然针对不同的JPA
提供商实现需要有不同的JpaBaseConfiguration
实现子类,但这些子类主要是将JPA
提供商实现信息包装成统一的格式供JpaBaseConfiguration
使用,而Spring Data JPA
主要工作组件的配置任务,还是主要落在JpaBaseConfiguration
身上。
JpaBaseConfiguration
主要是确保以下bean
的定义 :
-
PlatformTransactionManager transactionManager
仅在该类型的
bean
未被定义的情况下才定义
-
LocalContainerEntityManagerFactoryBean entityManagerFactory
仅在该类型的
bean
或者bean EntityManagerFactory
未被定义的情况下才定义
-
JpaVendorAdapter jpaVendorAdapter
仅在该类型的
bean
未被定义的情况下才定义;bean LocalContainerEntityManagerFactoryBean entityManagerFactory
定义的基础。
-
EntityManagerFactoryBuilder entityManagerFactoryBuilder
仅在该类型的
bean
未被定义的情况下才定义;bean LocalContainerEntityManagerFactoryBean entityManagerFactory
定义的基础。
可以这么理解,一个JpaBaseConfiguration
(当然具体类是它的某个实现子类)应用之后,我们就可以注入bean EntityManagerFactory
了。
源代码
源代码版本 : spring-boot-autoconfigure-2.1.3.RELEASE
package org.springframework.boot.autoconfigure.orm.jpa;
// 省略 imports
@Configuration
// 确保前缀为 spring.jpa 的属性被加载到 bean JpaProperties
@EnableConfigurationProperties(JpaProperties.class)
// 导入 DataSourceInitializedPublisher.Registrar, 用于向容器注册 bean DataSourceInitializedPublisher,
// DataSourceInitializedPublisher 是一个 BeanPostProcessor
@Import(DataSourceInitializedPublisher.Registrar.class)
public abstract class JpaBaseConfiguration implements BeanFactoryAware {
private final DataSource dataSource;
private final JpaProperties properties;
private final JtaTransactionManager jtaTransactionManager;
private final TransactionManagerCustomizers transactionManagerCustomizers;
private ConfigurableListableBeanFactory beanFactory;
// dataSource 在其他地方定义 :
// jtaTransactionManager 在其他地方定义 :
// transactionManagerCustomizers 在其他地方定义 :
// JpaProperties properties 来源参考本类注解
protected JpaBaseConfiguration(DataSource dataSource, JpaProperties properties,
ObjectProvider<JtaTransactionManager> jtaTransactionManager,
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
this.dataSource = dataSource;
this.properties = properties;
this.jtaTransactionManager = jtaTransactionManager.getIfAvailable();
this.transactionManagerCustomizers = transactionManagerCustomizers
.getIfAvailable();
}
// 定义 bean 事务处理器 PlatformTransactionManager transactionManager,
// 缺省情况下的实现类使用 JpaTransactionManager
@Bean
// 仅在该 bean 未被定义的情况下才定义
@ConditionalOnMissingBean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}
// 定义 bean JpaVendorAdapter jpaVendorAdapter, JPA供应商实现适配器
@Bean
// 仅在该 bean 未被定义的情况下才定义
@ConditionalOnMissingBean
public JpaVendorAdapter jpaVendorAdapter() {
AbstractJpaVendorAdapter adapter = createJpaVendorAdapter();
adapter.setShowSql(this.properties.isShowSql());
adapter.setDatabase(this.properties.determineDatabase(this.dataSource));
adapter.setDatabasePlatform(this.properties.getDatabasePlatform());
adapter.setGenerateDdl(this.properties.isGenerateDdl());
return adapter;
}
// 定义 bean EntityManagerFactoryBuilder entityManagerFactoryBuilder
// 该 bean 会使用其他地方定义的 JpaVendorAdapter, PersistenceUnitManager
// 构建一个 EntityManagerFactoryBuilder, 这是一个 EntityManagerFactory 构建器
// 此 bean 可以理解成底层组件提供者 JpaVendorAdapter, PersistenceUnitManager 跟
// 上层 LocalContainerEntityManagerFactoryBean 使用者之间的一个纽带
@Bean
// 仅在该 bean 未被定义的情况下才定义
@ConditionalOnMissingBean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(
JpaVendorAdapter jpaVendorAdapter,
ObjectProvider<PersistenceUnitManager> persistenceUnitManager,
ObjectProvider<EntityManagerFactoryBuilderCustomizer> customizers) {
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
jpaVendorAdapter, this.properties.getProperties(),
persistenceUnitManager.getIfAvailable());
customizers.orderedStream()
.forEach((customizer) -> customizer.customize(builder));
return builder;
}
// 定义 bean LocalContainerEntityManagerFactoryBean entityManagerFactory
// 该 bean 定义方法使用上面定义的 EntityManagerFactoryBuilder bean 执行其构建过程,
// 产出物为一个 LocalContainerEntityManagerFactoryBean , 这其实是一个
// EntityManagerFactory, EntityManager 的工厂组件 bean
@Bean
@Primary
// 仅在同类型 bean 和 类型为 EntityManagerFactory 的 bean 未被定义的情况下才定义
@ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class,
EntityManagerFactory.class })
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder factoryBuilder) {
Map<String, Object> vendorProperties = getVendorProperties();
customizeVendorProperties(vendorProperties);
return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan())
.properties(vendorProperties).mappingResources(getMappingResources())
.jta(isJta()).build();
}
protected abstract AbstractJpaVendorAdapter createJpaVendorAdapter();
protected abstract Map<String, Object> getVendorProperties();
/**
* Customize vendor properties before they are used. Allows for post processing (for
* example to configure JTA specific settings).
* @param vendorProperties the vendor properties to customize
*/
protected void customizeVendorProperties(Map<String, Object> vendorProperties) {
}
protected String[] getPackagesToScan() {
List<String> packages = EntityScanPackages.get(this.beanFactory)
.getPackageNames();
if (packages.isEmpty() && AutoConfigurationPackages.has(this.beanFactory)) {
packages = AutoConfigurationPackages.get(this.beanFactory);
}
return StringUtils.toStringArray(packages);
}
private String[] getMappingResources() {
List<String> mappingResources = this.properties.getMappingResources();
return (!ObjectUtils.isEmpty(mappingResources)
? StringUtils.toStringArray(mappingResources) : null);
}
/**
* Return the JTA transaction manager.
* @return the transaction manager or null
*/
protected JtaTransactionManager getJtaTransactionManager() {
return this.jtaTransactionManager;
}
/**
* Returns if a JTA PlatformTransactionManager is being used.
* @return if a JTA transaction manager is being used
*/
protected final boolean isJta() {
return (this.jtaTransactionManager != null);
}
/**
* Return the JpaProperties.
* @return the properties
*/
protected final JpaProperties getProperties() {
return this.properties;
}
/**
* Return the DataSource.
* @return the data source
*/
protected final DataSource getDataSource() {
return this.dataSource;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
}
// 内部配置类, 对 Open Session In View 模式的支持
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass(WebMvcConfigurer.class)
@ConditionalOnMissingBean({ OpenEntityManagerInViewInterceptor.class,
OpenEntityManagerInViewFilter.class })
@ConditionalOnMissingFilterBean(OpenEntityManagerInViewFilter.class)
@ConditionalOnProperty(prefix = "spring.jpa", name = "open-in-view",
havingValue = "true", matchIfMissing = true)
protected static class JpaWebConfiguration {
// Defined as a nested config to ensure WebMvcConfigurerAdapter is not read when
// not on the classpath
@Configuration
protected static class JpaWebMvcConfiguration implements WebMvcConfigurer {
private static final Log logger = LogFactory
.getLog(JpaWebMvcConfiguration.class);
private final JpaProperties jpaProperties;
protected JpaWebMvcConfiguration(JpaProperties jpaProperties) {
this.jpaProperties = jpaProperties;
}
@Bean
public OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor() {
if (this.jpaProperties.getOpenInView() == null) {
logger.warn("spring.jpa.open-in-view is enabled by default. "
+ "Therefore, database queries may be performed during view "
+ "rendering. Explicitly configure "
+ "spring.jpa.open-in-view to disable this warning");
}
return new OpenEntityManagerInViewInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addWebRequestInterceptor(openEntityManagerInViewInterceptor());
}
}
}
}