概述
HibernateJpaAutoConfiguration
是Spring Boot
针对使用JPA + Hibernate
的自动配置类,它的主要目的是在特定条件被满足的情况下导入配置类HibernateJpaConfiguration
。关于运行时使用的JPA + Hibernate
组件的真正的配置工作,被委托给了HibernateJpaConfiguration
来完成。
HibernateJpaAutoConfiguration
导入HibernateJpaConfiguration
的特定条件是 :
- 类
LocalContainerEntityManagerFactoryBean
和EntityManager
必须存在于classpath
; - 条件
HibernateEntityManagerCondition
必须被满足;条件
HibernateEntityManagerCondition
其实是HibernateJpaAutoConfiguration
自己定义的一个条件,
如果以下两个类之一存在于classpath
,则该条件被满足:org.hibernate.ejb.HibernateEntityManager
org.hibernate.jpa.HibernateEntityManager
在以上条件被满足的情况下,HibernateJpaAutoConfiguration
作了如下事情 :
- 确保
spring.jpa
为前缀的JPA
配置属性被加载到JpaProperties
bean
;这些属性会在随后
HibernateJpaConfiguration
工作时会被用到; - 导入
JPA + Hibernate
配置类HibernateJpaConfiguration
;
另外需要注意的是, 自动配置HibernateJpaAutoConfiguration
会发生在DataSourceAutoConfiguration
之后。这一点由注解@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
来定义。换句话讲,真正JPA + Hibernate
这些上层组件的配置,一定要发生在下层组件DataSource
的配置之后。
源代码
源代码版本 : spring-boot-autoconfigure-2.1.3.RELEASE
package org.springframework.boot.autoconfigure.orm.jpa;
// 省略 imports
@Configuration
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class })
@Conditional(HibernateEntityManagerCondition.class)
@EnableConfigurationProperties(JpaProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
@Import(HibernateJpaConfiguration.class)
public class HibernateJpaAutoConfiguration {
// 内嵌静态类,
// HibernateJpaAutoConfiguration 自定义的一个 SpringBootCondition 条件判断器,
// 给自己使用
// 如果以下两个类之一存在于 classpath , 则认为条件满足 , 否则认为条件不满足 :
// 1. org.hibernate.ejb.HibernateEntityManager
// 2. org.hibernate.jpa.HibernateEntityManager
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
static class HibernateEntityManagerCondition extends SpringBootCondition {
private static final String[] CLASS_NAMES = {
"org.hibernate.ejb.HibernateEntityManager",
"org.hibernate.jpa.HibernateEntityManager" };
@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)));
}
}
}