spring-data-JPA源碼解讀


spring-data-JPA源碼部分有兩個很重要的部分:1、識別repositories接口 2、將接口添加代理實現類並托管spring管理

JpaRepositoriesRegistrar

目的是將范圍內的接口准備作為springbean進行處理(有beanFactory輔助)

如果在啟動類上添加了@EnableJpaRepositories注解則我們按照如下思路分析

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(JpaRepositoriesRegistrar.class)//引入了JpaRepositoriesRegistrar
public @interface EnableJpaRepositories {

JpaRepositoriesRegistrar繼承了RepositoryBeanDefinitionRegistrarSupport並最終繼承了ImportBeanDefinitionRegistrar的重要方法registerBeanDefinitions

JpaRepositoriesRegistrar這個類本身指定好EnableJpaRepositories注解以及給出Extension,在Extension中主要的作用是限定本次注冊的factorybean是JpaRepositoryFactoryBean
@Override
protected Class<? extends Annotation> getAnnotation() {
return EnableJpaRepositories.class;
}

/* 
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getExtension()
*/
@Override
protected RepositoryConfigurationExtension getExtension() {
return new JpaRepositoryConfigExtension();
}

 

ImportBeanDefinitionRegistrar的作用是:
Interface to be implemented by types that register additional bean definitions when

processing @{@link Configuration} classes. Useful when operating at the bean definition
接口被實現成類型時需注冊成新的bean定義的過程
level (as opposed to {@code @Bean} method/instance level) is desired or necessary.
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfigurati……

spring在啟動過程中都是將配置文件(或者注解描述的信息)的信息解析成為一個個的BeanDefinition對象並裝入到容器的Bean定義注冊表(BeanDefinitionRegistry)中,但此時Bean還未初始化

 我們跟隨重要代碼片段向下走:

public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
        Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!");
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
        Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
        // Guard against calls for sub-classes
        if (annotationMetadata.getAnnotationAttributes(getAnnotation().getName()) == null) {
            return;
        }
        AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(
                annotationMetadata, getAnnotation(), resourceLoader, environment, registry);
        RepositoryConfigurationExtension extension = getExtension();
        RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);
        RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader,
                environment);
        //主要是這里面,Registers the found repositories in the given 根據給定的內容注冊beans
 delegate.registerRepositoriesIn(registry, extension);
    }
public List<BeanComponentDefinition> registerRepositoriesIn(BeanDefinitionRegistry registry,
      RepositoryConfigurationExtension extension) {
   extension.registerBeansForRoot(registry, configurationSource);
   RepositoryBeanDefinitionBuilder builder = new RepositoryBeanDefinitionBuilder(registry, extension, resourceLoader,
         environment);
   List<BeanComponentDefinition> definitions = new ArrayList<>();
   if (LOG.isDebugEnabled()) {
      LOG.debug("Scanning for repositories in packages {}.",
            configurationSource.getBasePackages().stream().collect(Collectors.joining(", ")));
   }
   //extension.getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)
   //這行代碼能夠掃描出所有的repository接口,下面是跟蹤代碼記錄點
   //org.springframework.data.repository.config.RepositoryConfigurationExtension#getRepositoryConfigurations(T, org.springframework.core.io.ResourceLoader, boolean)
   //org.springframework.data.repository.config.RepositoryConfigurationExtensionSupport#getRepositoryConfigurations(T, org.springframework.core.io.ResourceLoader, boolean)
   //org.springframework.data.repository.config.RepositoryConfigurationSource#getCandidates
   //org.springframework.data.repository.config.RepositoryConfigurationSourceSupport#getCandidates 這里獲得了所有符合條件的repository接口,向下看
   for (RepositoryConfiguration<? extends RepositoryConfigurationSource> configuration : extension .getRepositoryConfigurations(configurationSource, resourceLoader, inMultiStoreMode)) {
             //這里通過BeanDefinitionBuilder注冊的bean是JpaRepositoryFactoryBean,這個bean不是最后被代理的Repository接口
             //注冊bean的方式是spring的方式,把bean的定義信息加入定義列表,初始化bean時會自動創建JpaRepositoryFactoryBean,並執行afterPropertiesSet方法
             //(實現了InitializingBean接口),beanfactory的目的最終是創建bean的
             //spring啟動的第一步也是初始化BeanFactory
             //Spring將配置文件(或者注解描述的信息)的信息解析成為一個個的BeanDefinition對象並裝入到容器的Bean定義注冊表(BeanDefinitionRegistry)中,但此時Bean還未初始化
      BeanDefinitionBuilder definitionBuilder = builder.build(configuration);
      extension.postProcess(definitionBuilder, configurationSource);
      if (isXml) {
         extension.postProcess(definitionBuilder, (XmlRepositoryConfigurationSource) configurationSource);
      } else {
         extension.postProcess(definitionBuilder, (AnnotationRepositoryConfigurationSource) configurationSource);
      }
      AbstractBeanDefinition beanDefinition = definitionBuilder.getBeanDefinition();
      String beanName = configurationSource.generateBeanName(beanDefinition);
      if (LOG.isDebugEnabled()) {
         LOG.debug(REPOSITORY_REGISTRATION, extension.getModuleName(), beanName, configuration.getRepositoryInterface(),
               configuration.getRepositoryFactoryBeanClassName());
      }
      beanDefinition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, configuration.getRepositoryInterface());
      registry.registerBeanDefinition(beanName, beanDefinition);
      definitions.add(new BeanComponentDefinition(beanDefinition, beanName));
   }
   if (LOG.isDebugEnabled()) {
      LOG.debug("Finished repository scanning.");
   }
   return definitions;
}
RepositoryConfigurationSourceSupport
public Streamable<BeanDefinition> getCandidates(ResourceLoader loader) {
        //這個構造方法要去把掃描過濾器構建好 下看
        RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters(), registry);
        scanner.setConsiderNestedRepositoryInterfaces(shouldConsiderNestedRepositories());
        scanner.setEnvironment(environment);
        scanner.setResourceLoader(loader);
        getExcludeFilters().forEach(it -> scanner.addExcludeFilter(it));
        return Streamable.of(() -> getBasePackages().stream()//
                .flatMap(it -> scanner.findCandidateComponents(it).stream()));
    //scanner.findCandidateComponents(it)發現候選人
    //org.springframework.data.repository.config.RepositoryComponentProvider#findCandidateComponents
    //org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#findCandidateComponents
    //org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandidateComponents
    //這里面有判斷if (isCandidateComponent(metadataReader)) { 根據過濾器選擇class
    //Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); 所有的類
    //第二次才進來根據下面的過濾器選擇了repostory接口
}
//過濾器
//repository的規則
//構建掃描過濾器
//是Repository的接口 new InterfaceTypeFilter(Repository.class)
//有RepositoryDefinition注解 new AnnotationTypeFilter(RepositoryDefinition.class, true, true)
//排除NoRepositoryBean注解 addExcludeFilter(new AnnotationTypeFilter(NoRepositoryBean.class));
public RepositoryComponentProvider(Iterable<? extends TypeFilter> includeFilters, BeanDefinitionRegistry registry) {

   super(false);

   Assert.notNull(includeFilters, "Include filters must not be null!");
   Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");

   this.registry = registry;

   if (includeFilters.iterator().hasNext()) {
      for (TypeFilter filter : includeFilters) {
         addIncludeFilter(filter);
      }
   } else {
      super.addIncludeFilter(new InterfaceTypeFilter(Repository.class));
      super.addIncludeFilter(new AnnotationTypeFilter(RepositoryDefinition.class, true, true));
   }
   addExcludeFilter(new AnnotationTypeFilter(NoRepositoryBean.class));
}

至此,我們僅僅做到了掃描並識別出所有集成了Repository接口的JPA接口,並吧他們作為JpaRepositoryFactoryBean進行注冊(初始化),但是不要指望在這里找到實現JPA接口代理實現類

自動生成代理Bean實現,並托管spring管理

實例化JpaRepositoryFactoryBean時,由於接口實現了InitializingBean接口,FactoryBean初始化后執行了afterPropertiesSet,FactoryBean和bean是一整套的springbean生成體系

public abstract class RepositoryFactoryBeanSupport<T extends Repository<S, ID>, S, ID>
      implements InitializingBean, RepositoryFactoryInformation<S, ID>, FactoryBean<T>, BeanClassLoaderAware,
      BeanFactoryAware, ApplicationEventPublisherAware {
    //這個成員變量存儲了要被自動生成實現的repository接口(比如coffeeRepostory)
   private final Class<? extends T> repositoryInterface;
//org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean#afterPropertiesSet
public void afterPropertiesSet() {
   this.factory = createRepositoryFactory();
   this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey);
   this.factory.setNamedQueries(namedQueries);
   this.factory.setEvaluationContextProvider(evaluationContextProvider);
   this.factory.setBeanClassLoader(classLoader);
   this.factory.setBeanFactory(beanFactory);
   if (publisher != null) {
      this.factory.addRepositoryProxyPostProcessor(new EventPublishingRepositoryProxyPostProcessor(publisher));
   }
   repositoryBaseClass.ifPresent(this.factory::setRepositoryBaseClass);
   RepositoryFragments customImplementationFragment = customImplementation //
         .map(RepositoryFragments::just) //
         .orElseGet(RepositoryFragments::empty);
   RepositoryFragments repositoryFragmentsToUse = this.repositoryFragments //
         .orElseGet(RepositoryFragments::empty) //
         .append(customImplementationFragment);
   this.repositoryMetadata = this.factory.getRepositoryMetadata(repositoryInterface);
   // Make sure the aggregate root type is present in the MappingContext (e.g. for auditing)
   this.mappingContext.ifPresent(it -> it.getPersistentEntity(repositoryMetadata.getDomainType()));
   //這里將代理生成接口的實現
   this.repository = Lazy.of(() -> this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse));
   if (!lazyInit) {
      this.repository.get();
   }
}
public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fragments) {
   if (LOG.isDebugEnabled()) {
      LOG.debug("Initializing repository instance for {}…", repositoryInterface.getName());
   }
   Assert.notNull(repositoryInterface, "Repository interface must not be null!");
   Assert.notNull(fragments, "RepositoryFragments must not be null!");
   RepositoryMetadata metadata = getRepositoryMetadata(repositoryInterface);
   RepositoryComposition composition = getRepositoryComposition(metadata, fragments);
   RepositoryInformation information = getRepositoryInformation(metadata, composition);
   validate(information, composition);
   //這里返回了SimpleJpaRepository
   Object target = getTargetRepository(information);
   // 開始創建代理
   ProxyFactory result = new ProxyFactory();
   result.setTarget(target);//設置實現實體,這個實體類就是SimpleJpaRepository
   result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class);
   if (MethodInvocationValidator.supports(repositoryInterface)) {
      result.addAdvice(new MethodInvocationValidator());
   }
  //這些切點實現了接口中方法的執行! result.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE); result.addAdvisor(ExposeInvocationInterceptor.ADVISOR); postProcessors.forEach(processor
-> processor.postProcess(result, information)); result.addAdvice(new DefaultMethodInvokingMethodInterceptor()); ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory); result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory)); composition = composition.append(RepositoryFragment.implemented(target)); result.addAdvice(new ImplementationMethodExecutionInterceptor(composition)); //生成代理類 T repository = (T) result.getProxy(classLoader); if (LOG.isDebugEnabled()) { LOG.debug("Finished creation of repository instance for {}.", repositoryInterface.getName()); } return repository; }

不通過@EnableJpaRepositories注解,JPA如何自動配置

如果不熟悉springboot啟動自動配置的同學,請移步上一篇文章閱讀

spring-boot-autoconfigure包內的spring.factories文件內容,包含了JPA的,解釋了為什么沒有添加@EnableJpaRepositories仍然能用jpa

//JpaRepositoriesAutoConfiguration
@Configuration
    @ConditionalOnBean(DataSource.class) //當有DataSource的bean
@ConditionalOnClass(JpaRepository.class)//當classpath中有JpaRepository這個類
@ConditionalOnMissingBean({ JpaRepositoryFactoryBean.class, //沒有加載過JpaRepositoryFactoryBean、 JpaRepositoryConfigExtension兩個bean
      JpaRepositoryConfigExtension.class })
@ConditionalOnProperty(prefix = "spring.data.jpa.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)//有這個配置“spring.data.jpa.repositories.enabled=true”但不做強制檢查
@Import(JpaRepositoriesAutoConfigureRegistrar.class)
//看這個類JpaRepositoriesAutoConfigureRegistrar -> AbstractRepositoryConfigurationSourceSupport#registerBeanDefinitions 熟悉的方法
//new RepositoryConfigurationDelegate(getConfigurationSource(registry),
 //     this.resourceLoader, this.environment).registerRepositoriesIn(registry,
  //          getRepositoryConfigurationExtension());
@AutoConfigureAfter(HibernateJpaAutoConfiguration.class)
public class JpaRepositoriesAutoConfiguration {

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM