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...
- 下一篇
Spark Streaming场景应用- Spark Streaming计算模型及监控
摘要 Spark Streaming是一套优秀的实时计算框架。其良好的可扩展性、高吞吐量以及容错机制能够满足我们很多的场景应用。本篇文单在《Spark Streaming场景应用-Kafka数据读取方式》基础上,结合我们的应用场景,介结我们在使用Spark Streaming方面的技术架构,并着重讲解Spark Streaming两种计算模型,无状态和状态计算模型以及该两种模型的注意事项;接着介绍了Spark Streaming在监控方面所做的一些事情,最后总结了Spark Streaming的优缺点。 一、概述 数据是非常宝贵的资源,对各级企事业单均有非常高的价值。但是数据的爆炸,导致原先单机的数据处理已经无法满足业务的场景需求。因此在此基础上出现了一些优秀的分布式计算框架,诸如Hadoop、Spark等。离线分布式处理框架虽然能够处理非常大量的数据,但是其迟滞性很难满足一些特定的需求场景,比如push反馈、实时推荐、实时用户行为等。为了满足这些场景,使数据处理能够达到实时的响应和反馈,又随之出现了实时计算框架。目前的实时处理框架有Apache Storm、Apache Flink以...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS6,7,8上安装Nginx,支持https2.0的开启