spring-data-jpa原理探秘-运行环境创建及加载Repository接口
spring-data-jpa的优点很多,比如继承Repository接口,在注解中书写JPQL语句即可访问数据库;支持方法名解析方式访问数据库;使用Predicate支持动态查询等,在此不一一列举了。这些都是使用spring-data-jpa中的种种优点,要想将之使用的更好更优雅,就要从spring-data-jpa的加载和运行机制进行探秘。
此文系作者查看spring-data-jpa源码及参考javadoc文档成文,所以文中难免会有错误和纰漏,恳请读者指出。下面进入正题。
1.运行环境创建及加载Repository接口
spring-data-jpa在运行时和springframework框架实现了无缝对接。在使用spring的@Repository注解生成Repository实例时,使用动态代理类的方式对Repository接口进行了实例化并放入spring容器中备用。
下面是spring-data-jpa中占重要地位的RepositoryFactoryBeanSupport和RepositoryFactorySupport的类图:RepositoryFactoryBeanSupport的作用是,为spring的FactoryBean接口开发的适配器,可以很便捷的通过spring配置设置repository工厂;而RepositoryFactorySupport的作用是,创建一个给定repository接口实例的工厂bean。创建一个实现配置的repository接口的代理,并应用一个advice将控制交给QueryExecuterMethodInterceptor。
通过查看源码,我们可以看到在RepositoryFactoryBeanSupport中持有一个私有RepositoryFactorySupport类变量,在执行RepositoryFactoryBeanSupport.afterPropertiesSet()方法时,通过createRepositoryFactory()方法,new了一个JpaRepositoryFactory实例并赋值给了类变量factory(RepositoryFactorySupport),查看JpaRepositoryFactory的构造器,可以看到持有了entityManager等实例,以方便后面的使用。RepositoryFactoryBeanSupport中的private T initAndReturn()是另一个相当重要的方法,方法说明是:
Returns the previously initialized repository proxy or creates and returns the proxy if previously uninitialized.返回先前实例化了的repository代理实例,或者,如果先前没有实例化,那么生成并且返回一个代理实例。
为什么这么说明呢?我们来看代码,这个方法被另外两个方法调用,一个是afterPropertiesSet(),这是实现InitialingBean接口需要实现的一个加载方法,一般会先调用;另一个则是实现FactoryBean接口需要实现的getObject()方法,在运行中会调用之返回一个Repository接口的实例。所以,一般来说initAndReturn()至少会有两次被调用的机会。initAndReturn()的实现比较简单:
private T initAndReturn() { Assert.notNull(repositoryInterface, "Repository interface must not be null on initialization!"); if (this.repository == null) { this.repository = this.factory.getRepository(repositoryInterface, customImplementation); } return this.repository; }
通过RepositoryFactorySupport(JpaRepositoryFactory实例)的getRepository(repositoryInterface, customImplementation);获取了一个org.springframework.data.jpa.repository.support.SimpleJpaRepository代理类实例(定义为泛型T extends Repository),在构造这个实例时,进行了一系列的运行环境准备:
在RepositoryFactorySupport的内部类QueryExecutorMethodInterceptor中获取Query查找策略类QueryLookupStrategy实例(此处一般是CreateIfNotFoundQueryLookupStrategy实例),然后执行resolveQuery(method, repositoryInformation, factory, namedQueries);方法将RepositoryQuery实例执行循环放入RepositoryFactorySupport(JpaRepositoryFactory实例)的类变量queries,一个ConcurrentHashMap<Method, RepositoryQuery>中。
下图是QueryLookupStrategy的类图:
构造RepositoryQuery实例时对应了一个JpaQueryMethod实例,RepositoryQuery实例实际上是SimpleJpaQuery实例。
上面的描述总括上来说,就是一个通过spring框架生成(注意不是注入生成)的JpaRepositoryFactoryBean实例实现了InitialzingBean接口,在public void afterPropertiesSet()方法调用时生成了一个SimpleJpaRepository代理实例。SimpleJpaRepository实例中持有本次实例化的Repository代理类,以及在QueryExecutorMethodInterceptor构造器中实例化了的多个JpaQueryMethod,顾名思义,JpaQueryMethod就是jpa的带有@Query注解的方法数据存储类,所以Repository接口有多少个方法,就会包含多少个JpaQueryMethod实例被加入监听序列。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
深入剖析基于并发AQS的(独占锁)重入锁(ReetrantLock)及其Condition实现原理
在阅读本篇博文前,建议有CAS知识储备,因为关于CAS的操作在ReetrantLock的实现原理中可是随处可见,如没有了解过CAS可以先看博主的另一篇博文【Java并发编程-无锁CAS与Unsafe类及其并发包Atomic】,以下是本篇的主要内容 Lock接口 重入锁ReetrantLock 并发基础组件AQS与ReetrantLock AQS工作原理概要 基于ReetrantLock分析AQS独占模式实现过程 ReetrantLock中非公平锁 ReetrantLock中公平锁 关于synchronized 与ReentrantLock 神奇的Condition 关于Condition接口 Condition的使用案例-生产者消费者模式 Condition的实现原理 Lock接口 前面我们详谈过解决多线程同步问题的关键字synchronized,synchronized属于隐式锁,即锁的持有与释放都是隐式的,我们无需干预,而本篇我们要讲解的是显式锁,即锁的持有和释放都必须由我们手动编写。在Java 1.5中,官方在concurrent并发包中加入了Lock接口,该接口中提供了lock...
-
下一篇
如何用Nginx搭建一个安全的、快速的微服务架构
本文改编自Chris Stetson发表在nginx.conf 上的一个有关如今的微服务以及如何使用Nginx构建一个快速的、安全的网络系统的演讲, 自我介绍 Chris Stetson:Hi,我的名字是Chris Stetson,我在Nginx带领专业服务部门,同时也领导微服务实践。 今天我们要谈论微服务以及如何使用Nginx构建一个快速的、安全的网络系统。在我们谈话的最后,我们将与我们在Zokets的合作伙伴向您展示一个使用Fabric模式如何非常快速和轻松地构建一个微服务的demo。 在我们探讨Fabric模式之前,我想谈一谈微服务并且从Nginx的角度来看这意味着什么。 0:56 - 大转变 微服务已经引起了应用程序架构的重大转变。 当我第一次开始构建应用程序时,他们都是差不多的。幻灯片中所展示的单体架构也象征了应用程序的构造方式。 目前存在着某种类型的虚拟机(VM),对我来说,就是通常的Java。在虚拟机中应用的功能组件以对象的形式存在,这些对象是在内存中相互通讯的,它们将来来回回处理并进行方法调用。偶尔,你会采用诸如通知等机制来接触到其他系统以便获取数据或传递信息。 有了微...
相关文章
文章评论
共有0条评论来说两句吧...