Spring Data JPA 实现原理 您所在的位置:网站首页 jpa分页pageable原理 Spring Data JPA 实现原理

Spring Data JPA 实现原理

2023-03-31 07:43| 来源: 网络整理| 查看: 265

Spring Data JPA 实现原理

在使用Spring Data JPA的时候,只需使用简单的接口定义,通过JPA约定好的命名格式书写对于的方法,就能够完成日常开发中的大部分数据库交互的场景,看下官方给出的例子:

@Repository public interface SimpleUserRepository extends CrudRepository { /** * Find the user with the given username. This method will be translated into a query using the * {@link javax.persistence.NamedQuery} annotation at the {@link User} class. * * @param lastname * @return */ User findByTheUsersName(String username); /** * Uses {@link Optional} as return and parameter type. * * @param username * @return */ Optional findByUsername(Optional username); // ... }

可以知道,这里使用的是接口,而Java中的接口要使用必须要有实现类,那么JPA时怎么做到的呢,想到这里基本就可以猜出来Spring Data JPA是通过动态代理来实现,但是具体是怎么操作的呢?

从@EnableJpaRepositories说起

配置Spring Data JPA的时候通常就是通过@EnableJpaRepositories开启的,而通过注解就可以让整个JPA run起来,其中最重要的就是在@EnableJpaRepositories中import了JpaRepositoriesRegistrar,而这个配置就是入口所在。

先说明一下,Spring Data可不仅仅只有JPA的实现,还有其他各种各样的实现(如,JDBC,Redis,LDAP等),所以基本都是基于SPI(Service Provider Interface)解耦分层,所以大部分实现操作都是在spring-data-commons包中完成的。

JpaRepositoriesRegistrar

首先来看JpaRepositoriesRegistrar提供的功能,在spring-data-jpa包中,主要是用于告诉spring-data-commons抽象层的一些具体配置与解析: - getAnnotation(),提供JAP配置注解类,即@EnableJpaRepositories - getExtension(),提供JpaRepositoryConfigExtension,用于解析@EnableJpaRepositories

RepositoryBeanDefinitionRegistrarSupport

JpaRepositoriesRegistrar继承于RepositoryBeanDefinitionRegistrarSupport,它就是加载Repositories的关键: - registerBeanDefinitions,向Spring容器注册JpaRepositoryFactoryBean

大致步骤

所以,大致可以分为三大块,JPA加载的入口,注册JpaRepositoryFactoryBean和通过JpaRepositoryFactoryBean创建Repository - @EnableJpaRepositories import JpaRepositoriesRegistrar - JpaRepositoriesRegistrar.registerBeanDefinitions,注册JpaRepositoryFactoryBean - JpaRepositoryFactoryBean.afterPropertiesSet,创建Repository

JpaRepositoryFactoryBean如何创建Repository

其实,最关键的还是Repository是如何被创建出来的,首先看afterPropertiesSet

public void afterPropertiesSet() { this.factory = createRepositoryFactory(); this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey); this.factory.setNamedQueries(namedQueries); this.factory.setEvaluationContextProvider( evaluationContextProvider.orElseGet(() -> QueryMethodEvaluationContextProvider.DEFAULT)); 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())); //这里创建Repository this.repository = Lazy.of(() -> this.factory.getRepository(repositoryInterface, repositoryFragmentsToUse)); if (!lazyInit) { this.repository.get(); } }

具体来看RepositoryFactorySupport.getRepository()方法

public T getRepository(Class 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); //指定RepositoryBaseClass为SimpleJpaRepository RepositoryInformation information = getRepositoryInformation(metadata, composition); validate(information, composition); Object target = getTargetRepository(information); // Create proxy ProxyFactory result = new ProxyFactory(); result.setTarget(target); result.setInterfaces(repositoryInterface, Repository.class, TransactionalProxy.class); //Bean Validation Advice if (MethodInvocationValidator.supports(repositoryInterface)) { result.addAdvice(new MethodInvocationValidator()); } //事务 Advice result.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE); result.addAdvisor(ExposeInvocationInterceptor.ADVISOR); //RepositoryProxyPostProcessor处理 postProcessors.forEach(processor -> processor.postProcess(result, information)); //默认方法 Advice,背后实现为SimpleJpaRepository result.addAdvice(new DefaultMethodInvokingMethodInterceptor()); ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory); //自定义方法 Advice result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory)); composition = composition.append(RepositoryFragment.implemented(target)); //自定义实现方法的 Advice result.addAdvice(new ImplementationMethodExecutionInterceptor(composition)); //通过动态代理创建Repository T repository = (T) result.getProxy(classLoader); if (LOG.isDebugEnabled()) { LOG.debug("Finished creation of repository instance for {}.", repositoryInterface.getName()); } return repository; }

通过源码我们可以知道,Spring Data JPA是基于SimpleJpaRepository类的动态代理实现,通过AOP实现对自定义方法进行处理的。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有