背景
接上文:
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执行。
本文并没有做详细的分析,只是将核心的组件类一一点到,方便大家自行深入了解代码。