二十五、Spring Boot中spring-data-jpa自动配置源码分析

在上一节中,我们简单的讲述了jpa的查询语法和使用教程,而这一节咱们来看看Spring Boot中对jpa是如何进行自动配置的。

在Spring Boot自动配置的时候,一旦引入spring-boot-starter-data-jpa,就会完成JpaRepositoriesAutoConfiguration的自动配置。

JpaRepositoriesAutoConfiguration

@Configuration
@ConditionalOnBean(DataSource.class)
@ConditionalOnClass(JpaRepository.class)
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class,
        JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@Import(JpaRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration {}

spring-data-jpa底层使用的是Hibernate作为实现,所以jpa的自动配置操作在Hibernate的自动配置之后。

@AutoConfigureAfter:表示在指定类完成后再进行自动配置,所以来看HibernateJpaAutoConfiguration源码。

咱们继续:

HibernateJpaAutoConfiguration

@Configuration
@ConditionalOnClass({ LocalContainerEntityManagerFactoryBean.class, EntityManager.class })
@Conditional(HibernateEntityManagerCondition.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class })
public class HibernateJpaAutoConfiguration extends JpaBaseConfiguration {

    //other...
    
    public HibernateJpaAutoConfiguration(DataSource dataSource,
            JpaProperties jpaProperties,
            ObjectProvider jtaTransactionManager,
            ObjectProvider transactionManagerCustomizers) {
        //调用父类的构造方法
        super(dataSource, jpaProperties, jtaTransactionManager,
                transactionManagerCustomizers);
    }

    @Override
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Override
    protected Map getVendorProperties() {
        Map vendorProperties = new LinkedHashMap();
        vendorProperties.putAll(getProperties().getHibernateProperties(getDataSource()));
        return vendorProperties;
    }
    
    //other...
}

同样在HibernateJpaAutoConfiguration的源码中表示该自动配置需要在DataSourceAutoConfiguration完成后再进行,之前在分析JdbcTemplateAutoConfiguration的源码的时候已经分析过DataSourceAutoConfiguration,此处就不再讲述,一笔带过。

​ 回想之前在使用Spring和JPA集成的时候,会配置一个jpaVendorAdapter属性,一般使用HibernateJpaVendorAdapter作为JPA持久化实现厂商类。如下是spring和jpa集成时的部分配置:


    
        
    

​ 在JpaBaseConfiguration类中有个createJpaVendorAdapter()抽象方法,而在HibernateJpaAutoConfiguration类中进行了重载,创建使用HibernateJpaVendorAdapter作为JPA底层持久化实现厂商。

咱们来看父类的源码:

父类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,
            ObjectProvider transactionManagerCustomizers) {
        this.dataSource = dataSource;
        this.properties = properties;
        this.jtaTransactionManager = jtaTransactionManager.getIfAvailable();
        this.transactionManagerCustomizers = transactionManagerCustomizers
                .getIfAvailable();
    }

    //创建了TransactionManager的Bean
    @Bean
    @ConditionalOnMissingBean(PlatformTransactionManager.class)
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        if (this.transactionManagerCustomizers != null) {
            this.transactionManagerCustomizers.customize(transactionManager);
        }
        return transactionManager;
    }

    //创建了jpaVendorAdapter适配器,并填充相应属性,最后返回
    @Bean
    @ConditionalOnMissingBean
    public JpaVendorAdapter jpaVendorAdapter() {
        //通过HibernateJpaAutoConfiguration子类创建HibernateJpaVendorAdapter适配器
        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;
    }

    //通过jpaVendorAdapter与其他配置信息创建Builder构建器
    @Bean
    @ConditionalOnMissingBean
    public EntityManagerFactoryBuilder entityManagerFactoryBuilder(
            JpaVendorAdapter jpaVendorAdapter,
            ObjectProvider persistenceUnitManager) {
        EntityManagerFactoryBuilder builder = new EntityManagerFactoryBuilder(
                jpaVendorAdapter, this.properties.getProperties(),
                persistenceUnitManager.getIfAvailable());
        builder.setCallback(getVendorCallback());
        return builder;
    }

    //创建LocalContainerEntityManagerFactoryBean的Bean,用于JPA的容器管理EntityManagerFactory
    @Bean
    @Primary
    @ConditionalOnMissingBean({ LocalContainerEntityManagerFactoryBean.class,
            EntityManagerFactory.class })
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(
            EntityManagerFactoryBuilder factoryBuilder) {
        Map vendorProperties = getVendorProperties();
        customizeVendorProperties(vendorProperties);
        return factoryBuilder.dataSource(this.dataSource).packages(getPackagesToScan())
                .properties(vendorProperties).jta(isJta()).build();
    }

    //other...
}

在父类JpaBaseConfiguration中创建了几个重要的Bean,这样创建Bean的过程类似之前spring-jpa集成时使用的xml配置文件:


    
    
    
    
    
    




    

    
    
        
    

    
    
        
            true
            true
            update
        
    



    




通过这几步java配置,基本上就完成了之前spring-jpa集成所需的所有配置信息,当然Spring Boot内部做了很多工作,这里就不再描述了。

你可能感兴趣的:(二十五、Spring Boot中spring-data-jpa自动配置源码分析)