001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.data.jpa;
018
019import javax.sql.DataSource;
020
021import org.springframework.beans.factory.ObjectProvider;
022import org.springframework.boot.autoconfigure.AutoConfigureAfter;
023import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
024import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
025import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
026import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
027import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
028import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
029import org.springframework.boot.autoconfigure.orm.jpa.EntityManagerFactoryBuilderCustomizer;
030import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
031import org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration;
032import org.springframework.context.annotation.Bean;
033import org.springframework.context.annotation.Conditional;
034import org.springframework.context.annotation.Configuration;
035import org.springframework.context.annotation.Import;
036import org.springframework.core.task.AsyncTaskExecutor;
037import org.springframework.data.jpa.repository.JpaRepository;
038import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
039import org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension;
040import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
041
042/**
043 * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's JPA Repositories.
044 * <p>
045 * Activates when there is a bean of type {@link javax.sql.DataSource} configured in the
046 * context, the Spring Data JPA
047 * {@link org.springframework.data.jpa.repository.JpaRepository} type is on the classpath,
048 * and there is no other, existing
049 * {@link org.springframework.data.jpa.repository.JpaRepository} configured.
050 * <p>
051 * Once in effect, the auto-configuration is the equivalent of enabling JPA repositories
052 * using the {@link org.springframework.data.jpa.repository.config.EnableJpaRepositories}
053 * annotation.
054 * <p>
055 * This configuration class will activate <em>after</em> the Hibernate auto-configuration.
056 *
057 * @author Phillip Webb
058 * @author Josh Long
059 * @see EnableJpaRepositories
060 */
061@Configuration
062@ConditionalOnBean(DataSource.class)
063@ConditionalOnClass(JpaRepository.class)
064@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class,
065                JpaRepositoryConfigExtension.class })
066@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
067@Import(JpaRepositoriesAutoConfigureRegistrar.class)
068@AutoConfigureAfter({ HibernateJpaAutoConfiguration.class,
069                TaskExecutionAutoConfiguration.class })
070public class JpaRepositoriesAutoConfiguration {
071
072        @Bean
073        @Conditional(BootstrapExecutorCondition.class)
074        public EntityManagerFactoryBuilderCustomizer entityManagerFactoryBootstrapExecutorCustomizer(
075                        ObjectProvider<AsyncTaskExecutor> taskExecutor) {
076                return (builder) -> builder.setBootstrapExecutor(taskExecutor.getIfAvailable());
077        }
078
079        private static final class BootstrapExecutorCondition extends AnyNestedCondition {
080
081                BootstrapExecutorCondition() {
082                        super(ConfigurationPhase.REGISTER_BEAN);
083                }
084
085                @ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "bootstrap-mode", havingValue = "deferred", matchIfMissing = false)
086                static class DeferredBootstrapMode {
087
088                }
089
090                @ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "bootstrap-mode", havingValue = "lazy", matchIfMissing = false)
091                static class LazyBootstrapMode {
092
093                }
094
095        }
096
097}