Spring Data JPA 实现原理
Spring Data JPA 实现原理
在使用Spring Data JPA的时候,只需使用简单的接口定义,通过JPA约定好的命名格式书写对于的方法,就能够完成日常开发中的大部分数据库交互的场景,看下官方给出的例子:
@Repository
public interface SimpleUserRepository extends CrudRepository<User, Long> {
/**
* 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<User> findByUsername(Optional<String> 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> 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);
//指定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实现对自定义方法进行处理的