背景
接上文:
Spring Data JPA 简单介绍
本文将从配置解析,Bean的创建,Repository执行三个方面来简单介绍下Spring Data JPA的代码实现
友情提醒:
图片均可放大
配置解析
1. parser类
|
Spring通过Schema的方式进行配置,通过AbstractRepositoryConfigDefinitionParser进行解析。其中包含对NamedQuery的解析。
解析的主要目的,是将配置文件中的repositories和repository元素信息分别解析成GlobalRepositoryConfigInformation和SingleRepositoryConfigInformation。
详见下图 |
2. Information
|
CommonRepositoryConfigInformation:
xml中repositories的通用配置,一般对应其中的attributes
SingleRepositoryConfigInformation:
xml中repository的配置信息,对应其中的attributes
GlobalRepositoryCOnfigInformation:
一组SingleRepositoryConfigInfomation信息,包含所有的Single信息
在JPA实现中,针对Single,有两份实现,一份是自动配置信息,一份是手动配置信息,分别对应图中的Automatic和Manual。
SimpleJpaRepositoryConfiguration是JPA中的所有配置信息,包含所有的Jpa中的SingleRepositoryConfigInformation。 |
3. Query Lookup Strategy
| CreateQueryLookupStrategy:对应repositories元素query-lookup-strategy的create值,主要针对method query方式 DeclaredQueryLookupStrategy:对应use-declared-query值,主要针对带有@Query注解的查询方式 CreateIfNotFoundQueryLookupStrategy:对应create-if-not-found值(default值),结合了上述两种方式 |
Bean的创建
|
主要包含两个类
RepositoryFactoryBeanSupport, Spring Factory Bean,用于创建Reposiory代理类。其本身并不真正做代理的事情,只是接受Spring的配置,具体交由RepositoryFactorySupport进行代理工作
RepositoryFactorySupport, 真正做Repository代理工作,根据JpaRepositoryFactoryBean的定义找到TargetClass:SimpleJpaRepository实现类,中间加入3个拦截器,一个是异常翻译,一个是事务管理,最后一个是QueryExecutorMethodInterceptor。
QueryExecutorMethodInterceptor是个重点,主要做特定的Query(查询语句)的操作。 |
Repository执行
1. 主要执行类
|
在看上面Bean定义的时候,其实已经明白了执行过程: 1. 将JPA CRUD规范相关的方法交给SimpleJpaRepository这个类执行 2. 将特殊查询相关的交给QueryExecutorMethodInterceptor执行。主要做自定义实现的部分,method query部分和named query部分。 具体查询类详见下图。 |
2. 查询相关
| 主要支持NamedQuery和JPA Query。 |
主要执行代码
QueryExecutorMethodInterceptor#invoke(MethodInvocation invocation)
1 public Object invoke(MethodInvocation invocation) throws Throwable {
2
3 Method method = invocation.getMethod();
4
5 if (isCustomMethodInvocation(invocation)) {
6 Method actualMethod = repositoryInformation.getTargetClassMethod(method);
7 makeAccessible(actualMethod);
8 return executeMethodOn(customImplementation, actualMethod,
9 invocation.getArguments());
10 }
11
12 if (hasQueryFor(method)) {
13 return queries.get(method).execute(invocation.getArguments());
14 }
15
16 // Lookup actual method as it might be redeclared in the interface
17 // and we have to use the repository instance nevertheless
18 Method actualMethod = repositoryInformation.getTargetClassMethod(method);
19 return executeMethodOn(target, actualMethod,
20 invocation.getArguments());
21 }
主要分3个步骤:
1. 如果配置文件中执行了接口类的实现类,则直接交给实现类处理
2. 判断是查询方法的,交给RepositoryQuery实现,具体又分:NamedQuery,SimpleJpaQuery,PartTreeJpaQuery
3. 不属于上述两个,则直接将其交给真正的targetClass执行,在JPA中,就交给SimpleJpaRepository执行。
本文并没有做详细的分析,只是将核心的组件类一一点到,方便大家自行深入了解代码。