Spring JPA实现逻辑源码分析总结
1、SharedEntityManagerCreator: entitymanager的创建入口
该类被EntityManagerBeanDefinitionRegistrarPostProcessor注册到beanfactory中,依赖EntityManager bean实例的,
都会调用该类的工厂方法createSharedEntityManager,而该工厂方法的参数是EntityManagerFactory,通过BeanDefinitionUtils
找到类型为“EntityManagerFactory.class, AbstractEntityManagerFactoryBean.class”的所有BeanDefinition,针对找到的每个
BeanDefinition,注册一个EntityManager的BeanDefinition
- public class EntityManagerBeanDefinitionRegistrarPostProcessor implements BeanFactoryPostProcessor {
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- for (EntityManagerFactoryBeanDefinition definition : getEntityManagerFactoryBeanDefinitions(beanFactory)) {
- if (!(definition.getBeanFactory() instanceof BeanDefinitionRegistry)) {
- continue;
- }
- BeanDefinitionBuilder builder = BeanDefinitionBuilder
- .rootBeanDefinition("org.springframework.orm.jpa.SharedEntityManagerCreator");
- builder.setFactoryMethod("createSharedEntityManager");
- builder.addConstructorArgReference(definition.getBeanName());
- AbstractBeanDefinition emBeanDefinition = builder.getRawBeanDefinition();
- emBeanDefinition.addQualifier(new AutowireCandidateQualifier(Qualifier.class, definition.getBeanName()));
- emBeanDefinition.setScope(definition.getBeanDefinition().getScope());
- emBeanDefinition.setSource(definition.getBeanDefinition().getSource());
- BeanDefinitionReaderUtils.registerWithGeneratedName(emBeanDefinition,
- (BeanDefinitionRegistry) definition.getBeanFactory());
- }
- }
- }
2、JpaMetamodelMappingContextFactoryBean用来生成JpaMetamodelMappingContext
该FactoryBean创建实例时,遍历所有的EntityManagerFactory,调用EntityManagerFactory.getMetamodel,
将所有的Metamodel加入到一个集合,然后传入JpaMetamodelMappingContext,在将来创建Entity时使用。
- class JpaMetamodelMappingContextFactoryBean extends AbstractFactoryBean<JpaMetamodelMappingContext> implements
- ApplicationContextAware {
- private ListableBeanFactory beanFactory;
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.beanFactory = applicationContext;
- }
- @Override
- public Class<?> getObjectType() {
- return JpaMetamodelMappingContext.class;
- }
- @Override
- protected JpaMetamodelMappingContext createInstance() throws Exception {
- Set<Metamodel> models = getMetamodels();
- Set<Class<?>> entitySources = new HashSet<Class<?>>();
- for (Metamodel metamodel : models) {
- for (ManagedType<?> type : metamodel.getManagedTypes()) {
- Class<?> javaType = type.getJavaType();
- if (javaType != null) {
- entitySources.add(javaType);
- }
- }
- }
- JpaMetamodelMappingContext context = new JpaMetamodelMappingContext(models);
- context.setInitialEntitySet(entitySources);
- context.initialize();
- return context;
- }
- private Set<Metamodel> getMetamodels() {
- Collection<EntityManagerFactory> factories = BeanFactoryUtils.beansOfTypeIncludingAncestors(beanFactory,
- EntityManagerFactory.class).values();
- Set<Metamodel> metamodels = new HashSet<Metamodel>(factories.size());
- for (EntityManagerFactory emf : factories) {
- metamodels.add(emf.getMetamodel());
- }
- return metamodels;
- }
- }
3、JpaRepository中的EntityManager的注入也是通过SharedEntityManagerCreator的工厂方法创建的。
参见JpaRepositoryConfigExtension.getEntityManagerBeanDefinitionFor
4、PersistenceAnnotationBeanPostProcessor: 用来处理persistencecontext,persistenceunit两个注解
直接调用SharedEntityManagerCreator的createSharedEntityManager方法用来注入EntityManager,
位于PersistenceAnnotationBeanPostProcessor$PersistenceElement类内。
5、JpaRepositoryFactoryBean: 创建JpaRepository的工厂类, 实际委托给JpaRepositoryFactory类执行
在创建JpaRepositoryFactory时,通过加入TransactionalRepositoryProxyPostProcessor,在创建JpaRepository过程中
加入TransactionInterceptor,执行JpaRepository方法时,会自动加入事务处理。TransactionInterceptor中会注入配置的
TransactionManager(比如JpaTransactionManager)
6、EntityManager不是线程安全的,EntityManagerFactory是线程安全的
所以需要每次都在线程中生成新的EntityManager。因为注入到容器的EntityManager是个Proxy,所有的调用会委托给
SharedEntityManagerInvocationHandler去处理,间接的实现了线程安全。
7、TransactionSynchronizationManager: 使用ThreadLocal保存事务资源
8、直接通过注入EntityManger执行查询或者保存操作的,由于注入的EntityManager是SharedEntityManagerInvocationHandler的Proxy,
会通过EntityManagerFactoryUtils.doGetTransactionalEntityManager获取已经存在的事务的EntityManager,如果不存在,则会创建一个
EntityManager(有疑问),等调用结束,关闭该EntityManager。
参考:
Spring JPA实现逻辑源码分析总结的更多相关文章
- Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)
Spring Cloud 学习 之 Spring Cloud Eureka(源码分析) Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 ...
- spring boot 2.0 源码分析(一)
在学习spring boot 2.0源码之前,我们先利用spring initializr快速地创建一个基本的简单的示例: 1.先从创建示例中的main函数开始读起: package com.exam ...
- spring boot 2.0 源码分析(四)
在上一章的源码分析里,我们知道了spring boot 2.0中的环境是如何区分普通环境和web环境的,以及如何准备运行时环境和应用上下文的,今天我们继续分析一下run函数接下来又做了那些事情.先把r ...
- Spring中Bean命名源码分析
Spring中Bean命名源码分析 一.案例代码 首先是demo的整体结构 其次是各个部分的代码,代码本身比较简单,不是我们关注的重点 配置类 /** * @Author Helius * @Crea ...
- Spring Boot 自动配置 源码分析
Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration 下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的 ...
- Springboot中mybatis执行逻辑源码分析
Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...
- Spring基础系列-AOP源码分析
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9560803.html 一.概述 Spring的两大特性:IOC和AOP. AOP是面向切 ...
- 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)
1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...
- spring boot 2.0 源码分析(二)
在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /** * Run the ...
随机推荐
- AD域部署使用bginfo软件
实验网络拓扑图: 实验目标: bginfo收集信息服务器通过bginfo软件收集每个域客户端信息录入到SQL server 2008数据库 bginfo软件官网下载地址: https://docs.m ...
- WebView与 JS 交互方式
前言 现在很多App里都内置了Web网页(Hybrid App),比如说很多电商平台,淘宝.京东.聚划算等等,如下图 上述功能是由Android的WebView实现的,其中涉及到Android客户端与 ...
- 多线程开发之二 NSOperation
效果如下: ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UITableViewControll ...
- 和我一起学Effective Java之类和接口
类和接口 使类和成员的可访问性最小 信息隐藏(information hiding)/封装(encapsulation):隐藏模块内部数据和其他实现细节,通过API和其他模块通信,不知道其他模块的内部 ...
- spring与quartz定时器
参考: http://www.iteye.com/topic/399980 http://www.cnblogs.com/xrab/p/5850186.html
- 在linux中安装字体
https://blog.csdn.net/wangxintong_1992/article/details/81194896
- tar分层压缩
在Linux下使用 tar 命令来将文件打包并压缩是很通常的用法了. 可是Linux的文件系统对文件大小有限制,也就是说一个文件最大不能超过2G,如果压缩包的的内容很大,最后 的结果就会超过2G,又或 ...
- 浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制
JAVA中的部分需要扩容的内容总结如下:第一部分: HashMap<String, String> hmap=new HashMap<>(); HashSet<Strin ...
- 返回一个数组升序排列后的位置信息--C#程序举例
返回一个数组升序排列后的位置信息--C#程序举例 返回某一个数组升序排序后的位置 比如:{8,10,9,11}排序后应该是{8,9,10,11},但是需要返回{1,3,2,4} 大概记忆里是这么 ...
- Xcode连接TFS Git用户名和密码不正确解决方案
团队要将原来搭建的Git服务全部迁移到TFS的Git上统一管理,迁移的过程非常顺利.当要用Xcode或者SourceTree连接TFS Git(我们的TFS身份认证是基于Windows的,使用HTTP ...