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 ...
随机推荐
- Android qualcomm WCNSS_qcom_cfg.ini 参数介绍
本文介绍WCNSS_qcom_cfg.ini中常用参数的作用. wifi 日志等级 vosTraceEnableBAP=255 vosTraceEnableTL=255 vosTraceEnableW ...
- Python_建造者模式
#!/usr/bin/python # -*- coding:utf-8 -*- #建造者基类 class PersonBuilder(): def BuildHead(self): pass def ...
- Spark学习笔记——在集群上运行Spark
Spark运行的时候,采用的是主从结构,有一个节点负责中央协调, 调度各个分布式工作节点.这个中央协调节点被称为驱动器( Driver) 节点.与之对应的工作节点被称为执行器( executor) 节 ...
- vue返回上一页面如果没有上一页面返回首页
methods: { back(){ if (window.history.length <= 1) { this.$router.push({path:'/'}) return false } ...
- mongodb查询数据库中某个字段中的值包含某个字符串的方法
正则表达式最能解决: 例如: db.getCollection(.*$/}) 这里主要是注意正则表达式要写对,该转义的注意转义,否则报错.
- IntellIJ IDEA 配置 Vue 支持
IDEA版本: IntelliJ IDEA 2017.2Build #IU-172.3317.76, built on July 15, 2017Licensed to Administrator J ...
- Orleans学习总结(五)--监控篇
上篇说完了Orleans学习总结(四)--集群配置篇,这次我们来说下监控 Orleans有一个强大的社区,为Orleans开发着各种各样的扩展工具,我们用的是OrleansDashboard.Dash ...
- VMWARE虚拟机不显示主机共享的文件夹解决办法
执行如下命令重新配置,不用重启. #sudo vmware-config-tools.pl
- JS 通过字符串取得对应对象
//对Array的扩展,查找所有满足条件的元素 Array.prototype.findAll = function (match) { var tmp = []; for (var i = 0; i ...
- sql语句 isnull(列名,'')='' /STUFF的意思
(1) SELECT SYXH,ZYHM,YEXH,ISNULL(YETZ,'') AS YETZ ,RYKSMC,RYBQMC,HZXM FROM YG_BRSYK 如果列名数据等于NULL,那么 ...