背景
在Spring Data之JPA开篇中可以看到Spring Boot的启动日志,先是创建了HikariDataSource,然后紧接着构建了EntityManagerFactory
2018-10-25 09:32:20.645 INFO 37469 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2018-10-25 09:32:20.791 INFO 37469 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2018-10-25 09:32:20.846 INFO 37469 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
- 1
- 2
- 3
其中HikariDataSource的创建在Spring Data之DataSource创建及源码分析中进行了介绍,这篇文章我们就来探寻一下EntityManagerFactory是如何自动创建出来的。
JPA规范
首先有必要了解一下JPA规范(JSR 338)以便更好的理解EntityManagerFactory的创建过程。
JSR 338主要定义了如何通过普通的Java domain进行关系数据库的操作及映射,其中主要概念包含如下:
- Entity
- 必须是顶级类
- @Entity注解的类
- 必须有一个无参的public 或 protected的构造方法
- 不能是final类,且不能有final方法或final变量
- 一个Entity类通常与数据库的一张表进行对应
- 一个Entity实例表现为数据库的一条数据
- 对Entity的操作即对数据库的操作
- 生命周期包含初始、托管、释放、消亡
- EntityManager
- 对Entity持久化操作的主要对象
- 通过EntityManagerFactory获取实例
- 一个实例代表一个数据库连接
- 每个线程拥有自己的EntityManager实例
- 主要方法有persist、remove、merge、createQuery、find
- 可使用@PersistenceContext注入
- EntityManagerFactory
- 创建EntityManager的工厂
- EntityManagerFactory的创建成本很高,对于给定的数据库,系统应该只创建一个与之关联的Factory
- 可使用@PersistenceUnit注入
- EntityTransaction
- 表示数据库事务,在增、删、改时使用
- 可通过EntityManager.getTransaction()获取
- Persistence Context
- 维护一组托管状态的Entity实例
- 与EntityManager是相关联的
- Persistence Unit
- 一组Entity及相关设置的逻辑单元
- 定义创建EntityManagerFactory所需要的参数
- 通过persistence.xml定义或者通过一个PersistenceUnitInfo对象
总结一下,通过Persistence Unit创建EntityManagerFactory,再通过EntityManagerFactory获取EntityManager。下面我们就按照这个方向进行源码分析。
自动配置
同DataSource一样,EntityManagerFactory的创建也是通过一些列@Conditional的注解最终找到Hibernate的实现。我们先看下自动配置的入口类HibernateJpaAutoConfiguration
@Configuration
//先校验是否存在LocalContainerEntityManagerFactoryBean
//该类是spring-orm包中的类,从名称上看就知道是跟EntityManagerFactory的创建有关的
//要使用JPA,EntityManager自然也是要存在的
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class })
//自定义的校验类,校验是否存在CLASS_NAMES中的类
@Conditional(HibernateEntityManagerCondition.class)
//在application.properties中配置的spring.jpa开头的设置,会注入到JpaProperties中
//换句话说在spring.jpa能设置什么,要看JpaProperties有什么属性
@EnableConfigurationProperties(JpaProperties.class)
//这个设置很关键,意思是要在DataSource之后再创建,因为JPA会用到DataSource
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
//上面的校验都满足后,则进入HibernateJpaConfiguration
@Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
static class HibernateEntityManagerCondition extends SpringBootCondition {
private static final String[] CLASS_NAMES = {
"org.hibernate.ejb.HibernateEntityManager",
"org.hibernate.jpa.HibernateEntityManager" };
/**
* 通过ClassUtils.isPresent检查是否存在CLASS_NAMES中指定的类
*/
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
ConditionMessage.Builder message = ConditionMessage
.forCondition("HibernateEntityManager");
for (String className : CLASS_NAMES) {
if (ClassUtils.isPresent(className, context.getClassLoader())) {
return ConditionOutcome
.match(message.found("class").items(Style.QUOTE, className));
}
}
return ConditionOutcome.noMatch(message.didNotFind("class", "classes")
.items(Style.QUOTE, Arrays.asList(CLASS_NAMES)));
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
主要逻辑已在代码中添加注释说明,接下来就看下@Import的HibernateJpaConfiguration
@Configuration
@ConditionalOnSingleCandidate(DataSource.class)
class HibernateJpaConfiguration extends JpaBaseConfiguration {
//省略。。。
@Override
protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
return new HibernateJpaVendorAdapter();
}
//省略。。。
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
省略了一些不重要的代码,只留下createJpaVendorAdapter方法。再接着看父类JpaBaseConfiguration
@EnableConfigurationProperties(JpaProperties.class)
@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;
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
@ConditionalOnMissingBean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
if (this.transactionManagerCustomizers != null) {
this.transactionManagerCustomizers.customize(transactionManager);
}
return transactionManager;
}
@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
@ConditionalOnMissingBean
public EntityManagerFactoryBuilder entityManagerFactoryBuilder(
JpaVendorAdapter jpaVendorAdapter,
ObjectProvider<PersistenceUnitManager> persistenceUnitManager) {
EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
jpaVendorAdapter, this.properties.getProperties(),
persistenceUnitManager.getIfAvailable());
builder.setCallback(getVendorCallback());
return builder;
}
@Bean
@Primary
@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();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
可以看到该类有4个@Bean注解的方法,咱们按顺序分析
-
transactionManager
创建JPA事务的管理器 -
jpaVendorAdapter
JpaVendorAdapter是一个接口,里面有一个方法是getPersistenceProvider,而PersistenceProvider是JPA规范中定义的创建EntityManagerFactory的接口方法。
createJpaVendorAdapter的实现是在HibernateJpaConfiguration中返回的是 HibernateJpaVendorAdapter.public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter{ private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect(); private final PersistenceProvider persistenceProvider; private final Class<? extends EntityManagerFactory> entityManagerFactoryInterface; private final Class<? extends EntityManager> entityManagerInterface; /** * 明确指明了persistenceProvider的实现是SpringHibernateJpaPersistenceProvider */ @SuppressWarnings("deprecation") public HibernateJpaVendorAdapter() { this.persistenceProvider = new SpringHibernateJpaPersistenceProvider(); this.entityManagerFactoryInterface = org.hibernate.jpa.HibernateEntityManagerFactory.class; this.entityManagerInterface = org.hibernate.jpa.HibernateEntityManager.class; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
/** * 继承了Hibernate的PersistenceProvider */ class SpringHibernateJpaPersistenceProvider extends HibernatePersistenceProvider{ /** * 重要方法,调用了Hibernate的EntityManagerFactoryBuilderImpl,通过build创建出了EntityManagerFactory */ public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) { final List<String> mergedClassesAndPackages = new ArrayList<>(info.getManagedClassNames()); if (info instanceof SmartPersistenceUnitInfo) { mergedClassesAndPackages.addAll(((SmartPersistenceUnitInfo) info).getManagedPackages()); } return new EntityManagerFactoryBuilderImpl( new PersistenceUnitInfoDescriptor(info) { @Override public List<String> getManagedClassNames() { return mergedClassesAndPackages; } }, properties).build(); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
-
entityManagerFactoryBuilder
建造者模式,将需要的原料都准备好 -
entityManagerFactory
LocalContainerEntityManagerFactoryBean就是启动日志中打印出*Building JPA container EntityManagerFactory for persistence unit ‘default’*的类。
该类及其父类AbstractEntityManagerFactoryBean包含了创建EntityManagerFactory的所有元素,前面的步骤都是在为LocalContainerEntityManagerFactoryBean的属性准备数据赋值public class LocalContainerEntityManagerFactoryBean extends AbstractEntityManagerFactoryBean implements ResourceLoaderAware, LoadTimeWeaverAware { /** *根据provider(前面提到的SpringHibernateJpaPersistenceProvider)创建EntityManagerFactory */ protected EntityManagerFactory createNativeEntityManagerFactory() throws PersistenceException { Assert.state(this.persistenceUnitInfo != null, "PersistenceUnitInfo not initialized"); PersistenceProvider provider = getPersistenceProvider(); if (provider == null) { String providerClassName = this.persistenceUnitInfo.getPersistenceProviderClassName(); if (providerClassName == null) { throw new IllegalArgumentException( "No PersistenceProvider specified in EntityManagerFactory configuration, " + "and chosen PersistenceUnitInfo does not specify a provider class name either"); } Class<?> providerClass = ClassUtils.resolveClassName(providerClassName, getBeanClassLoader()); provider = (PersistenceProvider) BeanUtils.instantiateClass(providerClass); } if (logger.isInfoEnabled()) { logger.info("Building JPA container EntityManagerFactory for persistence unit '" + this.persistenceUnitInfo.getPersistenceUnitName() + "'"); } EntityManagerFactory emf = provider.createContainerEntityManagerFactory(this.persistenceUnitInfo, getJpaPropertyMap()); postProcessEntityManagerFactory(emf, this.persistenceUnitInfo); return emf; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
需要注意的是AbstractEntityManagerFactoryBean有两个EntityManagerFactory类型的属性,一个是通过PersistenceProvider获取的原生对象,另一个是Spring创建的代理对象ManagedEntityManagerFactoryInvocationHandler,它的目的是为了拦截EntityManager的创建,至少为什么要代理,下篇文档会进行分析。
结束语
到这里EntityManagerFactory就创建出来了,总的来说整个过程是遵循JPA规范定义的接口的,例如SpringHibernateJpaPersistenceProvider实现的createContainerEntityManagerFactory方法。只不过Spring作为骨干框架,使用了很多中间对象和过程。
最后用一张类图,再串一下创建的过程
-
首先以左下角的HibernateJpaAutoConfiguration为入口,经过@Conditional的判断,@Import进入HibernateJpaConfiguration
-
在HibernateJpaConfiguration中依赖类HibernateJpaVendorAdapter,而HibernateJpaVendorAdapter又依赖了SpringHibernateJpaPersistenceProvider,PersistenceProvider的具体实现就确定了
-
在JpaBaseConfiguration中通过EntityManagerFactoryBuilder创建出了LocalContainerEntityManagerFactoryBean,该类是整个结构的纽带。可以看到它关联了PersistenceProvider和PersistenceUnitManager,而PersistenceUnitManager是产生PersistenceUnitInfo的,PersistenceProvider和PersistenceUnitInfo是createEntityFactory的两个必要对象
-
最后在LocalContainerEntityManagerFactoryBean中调用SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory创建出了EntityManagerFactory
那么EntityManagerFactory创建出来后有什么用呢,当然是用来获取EntityManager,下篇文章我们继续分析EntityManager的创建过程。