zoukankan      html  css  js  c++  java
  • 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 {
    
    }

  • 相关阅读:
    常用代码片段
    《资本论》读书笔记(1)谁偷了我的奶酪
    《资本论》读书笔记(0)为了弄清楚经济学规律
    [转]如何理解矩阵乘法的规则
    Nginx编译安装lua-nginx-module
    Supervisor使用教程
    ELK实践(二):收集Nginx日志
    ELK实践(一):基础入门
    MySQL大批量导入导出实践
    Elasticsearch实践(四):IK分词
  • 原文地址:https://www.cnblogs.com/zxporz/p/10701830.html
Copyright © 2011-2022 走看看