4. Spring Data JPA 原理
4.1 思考
4.2 源码分析
4.2.1 Spring Data Jpa 自动配置
@Import org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesRegistrar
在该类中配置了 @EnableJpaRepositories
@Import org.springframework.data.jpa.repository.config.JpaRepositoriesRegistrar
集成RepositoryBeanDefinitionRegistrarSupport
java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class JpaRepositoriesRegistrar extends RepositoryBeanDefinitionRegistrarSupport { @Override protected Class<? extends Annotation > getAnnotation() { return EnableJpaRepositories.class; } @Override protected RepositoryConfigurationExtension getExtension () { return new JpaRepositoryConfigExtension (); } }
4.2.2. 创建JpaRepositoryFactoryBean
RepositoryBeanDefinitionRegistrarSupport
实现ImportBeanDefinitionRegistrar
java
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 package org.springframework.data.repository.config;import java.lang.annotation.Annotation;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.beans.factory.support.BeanNameGenerator;import org.springframework.context.EnvironmentAware;import org.springframework.context.ResourceLoaderAware;import org.springframework.context.annotation.ConfigurationClassPostProcessor;import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;import org.springframework.core.env.Environment;import org.springframework.core.io.ResourceLoader;import org.springframework.core.type.AnnotationMetadata;import org.springframework.lang.NonNull;import org.springframework.util.Assert;public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar , ResourceLoaderAware, EnvironmentAware { @NonNull private ResourceLoader resourceLoader; @NonNull private Environment environment; public RepositoryBeanDefinitionRegistrarSupport () { } public void setResourceLoader (ResourceLoader resourceLoader) { this .resourceLoader = resourceLoader; } public void setEnvironment (Environment environment) { this .environment = environment; } @Deprecated public void registerBeanDefinitions (AnnotationMetadata metadata, BeanDefinitionRegistry registry) { this .registerBeanDefinitions(metadata, registry, ConfigurationClassPostProcessor.IMPORT_BEAN_NAME_GENERATOR); } public void registerBeanDefinitions (AnnotationMetadata metadata, BeanDefinitionRegistry registry, BeanNameGenerator generator) { Assert.notNull(metadata, "AnnotationMetadata must not be null!" ); Assert.notNull(registry, "BeanDefinitionRegistry must not be null!" ); Assert.notNull(this .resourceLoader, "ResourceLoader must not be null!" ); if (metadata.getAnnotationAttributes(this .getAnnotation().getName()) != null ) { AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource (metadata, this .getAnnotation(), this .resourceLoader, this .environment, registry, generator); RepositoryConfigurationExtension extension = this .getExtension(); RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource); RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate (configurationSource, this .resourceLoader, this .environment); delegate.registerRepositoriesIn(registry, extension); } } protected abstract Class<? extends Annotation > getAnnotation(); protected abstract RepositoryConfigurationExtension getExtension () ; }
最终生成代理类
4.2.3. 代理类SimpleJpaRepository
上一步我们确定了,jps是通过创建factory动态创建repository的,先看一看JpaRepositoryFactoryBean
源码
java
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 public void afterPropertiesSet () { this .factory = this .createRepositoryFactory(); this .factory.setQueryLookupStrategyKey(this .queryLookupStrategyKey); this .factory.setNamedQueries(this .namedQueries); this .factory.setEvaluationContextProvider((QueryMethodEvaluationContextProvider)this .evaluationContextProvider.orElseGet(() -> { return QueryMethodEvaluationContextProvider.DEFAULT; })); this .factory.setBeanClassLoader(this .classLoader); this .factory.setBeanFactory(this .beanFactory); if (this .publisher != null ) { this .factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor (this .publisher)); } RepositoryFactorySupport var10001 = this .factory; this .repositoryBaseClass.ifPresent(var10001::setRepositoryBaseClass); this .repositoryFactoryCustomizers.forEach((customizer) -> { customizer.customize(this .factory); }); RepositoryFragments customImplementationFragment = (RepositoryFragments)this .customImplementation.map((xva$0 ) -> { return RepositoryFragments.just(new Object []{xva$0 }); }).orElseGet(RepositoryFragments::empty); RepositoryFragments repositoryFragmentsToUse = ((RepositoryFragments)this .repositoryFragments.orElseGet(RepositoryFragments::empty)).append(customImplementationFragment); this .repositoryMetadata = this .factory.getRepositoryMetadata(this .repositoryInterface); this .repository = Lazy.of(() -> { return (Repository)this .factory.getRepository(this .repositoryInterface, repositoryFragmentsToUse); }); this .mappingContext.ifPresent((it) -> { it.getPersistentEntity(this .repositoryMetadata.getDomainType()); }); if (!this .lazyInit) { this .repository.get(); } }
顺着getRepository方法继续追踪
java
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 public <T> T getRepository (Class<T> repositoryInterface, RepositoryFragments fragments) { if (logger.isDebugEnabled()) { logger.debug(LogMessage.format("Initializing repository instance for %s…" , repositoryInterface.getName())); } Assert.notNull(repositoryInterface, "Repository interface must not be null!" ); Assert.notNull(fragments, "RepositoryFragments must not be null!" ); ApplicationStartup applicationStartup = getStartup(); StartupStep repositoryInit = onEvent(applicationStartup, "spring.data.repository.init" , repositoryInterface); repositoryBaseClass.ifPresent(it -> repositoryInit.tag("baseClass" , it.getName())); StartupStep repositoryMetadataStep = onEvent(applicationStartup, "spring.data.repository.metadata" , repositoryInterface); RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface); repositoryMetadataStep.end(); StartupStep repositoryCompositionStep = onEvent(applicationStartup, "spring.data.repository.composition" , repositoryInterface); repositoryCompositionStep.tag("fragment.count" , String.valueOf(fragments.size())); RepositoryComposition composition = getRepositoryComposition(metadata, fragments); RepositoryInformation information = getRepositoryInformation(metadata, composition); return repository; }
java
1 2 3 4 5 6 7 8 9 10 11 12 13 private RepositoryInformation getRepositoryInformation (RepositoryMetadata metadata, RepositoryComposition composition) { RepositoryInformationCacheKey cacheKey = new RepositoryInformationCacheKey (metadata, composition); return repositoryInformationCache.computeIfAbsent(cacheKey, key -> { Class<?> baseClass = repositoryBaseClass.orElse(getRepositoryBaseClass(metadata)); return new DefaultRepositoryInformation (metadata, baseClass, composition); }); }
RepositoryFactorySupport
java
1 2 3 4 5 6 7 8 protected abstract Class<?> getRepositoryBaseClass(RepositoryMetadata metadata);
JpaRepositoryFactory
java
1 2 3 4 5 6 7 8 public class JpaRepositoryFactory extends RepositoryFactorySupport { @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) { return SimpleJpaRepository.class; } }
4.2.4. Spring Data JPA 是怎么匹配Repository接口的?
RepositoryConfigurationExtensionSupport
java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 protected boolean isStrictRepositoryCandidate (RepositoryMetadata metadata) { if (noMultiStoreSupport) { return false ; } Collection<Class<?>> types = getIdentifyingTypes(); Collection<Class<? extends Annotation >> annotations = getIdentifyingAnnotations(); String moduleName = getModuleName(); if (types.isEmpty() && annotations.isEmpty()) { if (!noMultiStoreSupport) { logger.warn(LogMessage.format("Spring Data %s does not support multi-store setups!" , moduleName)); noMultiStoreSupport = true ; return false ; } }
JpaRepositoryConfigExtension
java
1 2 3 4 @Override protected Collection<Class<?>> getIdentifyingTypes() { return Collections.<Class<?>> singleton(JpaRepository.class); }
4.3 总结