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

在上一節(jié)中,我們簡單的講述了jpa的查詢語法和使用教程,而這一節(jié)咱們來看看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作為實現(xiàn),所以jpa的自動配置操作在Hibernate的自動配置之后。

@AutoConfigureAfter:表示在指定類完成后再進行自動配置,所以來看HibernateJpaAutoConfiguration源碼。

咱們繼續(xù):

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> jtaTransactionManager,
            ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
        //調(diào)用父類的構(gòu)造方法
        super(dataSource, jpaProperties, jtaTransactionManager,
                transactionManagerCustomizers);
    }

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

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

同樣在HibernateJpaAutoConfiguration的源碼中表示該自動配置需要在DataSourceAutoConfiguration完成后再進行,之前在分析JdbcTemplateAutoConfiguration的源碼的時候已經(jīng)分析過DataSourceAutoConfiguration,此處就不再講述,一筆帶過。

? 回想之前在使用Spring和JPA集成的時候,會配置一個jpaVendorAdapter屬性,一般使用HibernateJpaVendorAdapter作為JPA持久化實現(xiàn)廠商類。如下是spring和jpa集成時的部分配置:

<property name="jpaVendorAdapter">
    <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        <!-- 該bean的屬性配置 -->
    </bean>
</property>

? 在JpaBaseConfiguration類中有個createJpaVendorAdapter()抽象方法,而在HibernateJpaAutoConfiguration類中進行了重載,創(chuàng)建使用HibernateJpaVendorAdapter作為JPA底層持久化實現(xiàn)廠商。

咱們來看父類的源碼:

父類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();
    }

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

    //創(chuàng)建了jpaVendorAdapter適配器,并填充相應(yīng)屬性,最后返回
    @Bean
    @ConditionalOnMissingBean
    public JpaVendorAdapter jpaVendorAdapter() {
        //通過HibernateJpaAutoConfiguration子類創(chuàng)建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與其他配置信息創(chuàng)建Builder構(gòu)建器
    @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;
    }

    //創(chuàng)建LocalContainerEntityManagerFactoryBean的Bean,用于JPA的容器管理EntityManagerFactory
    @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).jta(isJta()).build();
    }

    //other...
}

在父類JpaBaseConfiguration中創(chuàng)建了幾個重要的Bean,這樣創(chuàng)建Bean的過程類似之前spring-jpa集成時使用的xml配置文件:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="${jdbc.driverClass}"></property>
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
    <property name="user" value="${jdbc.user}"></property>
    <property name="password" value="${jdbc.password}"></property>
    <property name="initialPoolSize" value="${jdbc.initialPoolSize}"></property>
    <property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
</bean>

<!-- 配置jpa的EntityManagerFactory -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"></property>

    <!-- 配置jpa生產(chǎn)商的適配器 -->
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
    </property>

    <!-- 配置jpa的基本屬性 -->
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">update</prop>
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>

<!-- 配置SpringData -->
<jpa:repositories base-package="xxxxx包名" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="transactionManager"></jpa:repositories>

通過這幾步j(luò)ava配置,基本上就完成了之前spring-jpa集成所需的所有配置信息,當(dāng)然Spring Boot內(nèi)部做了很多工作,這里就不再描述了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容