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实现逻辑源码分析总结

从EnableJpaRepository说开去

Spring JPA实现逻辑源码分析总结的更多相关文章

  1. Spring Cloud 学习 之 Spring Cloud Eureka(源码分析)

    Spring Cloud 学习 之 Spring Cloud Eureka(源码分析) Spring Boot版本:2.1.4.RELEASE Spring Cloud版本:Greenwich.SR1 ...

  2. spring boot 2.0 源码分析(一)

    在学习spring boot 2.0源码之前,我们先利用spring initializr快速地创建一个基本的简单的示例: 1.先从创建示例中的main函数开始读起: package com.exam ...

  3. spring boot 2.0 源码分析(四)

    在上一章的源码分析里,我们知道了spring boot 2.0中的环境是如何区分普通环境和web环境的,以及如何准备运行时环境和应用上下文的,今天我们继续分析一下run函数接下来又做了那些事情.先把r ...

  4. Spring中Bean命名源码分析

    Spring中Bean命名源码分析 一.案例代码 首先是demo的整体结构 其次是各个部分的代码,代码本身比较简单,不是我们关注的重点 配置类 /** * @Author Helius * @Crea ...

  5. Spring Boot 自动配置 源码分析

    Spring Boot 最大的特点(亮点)就是自动配置 AutoConfiguration 下面,先说一下 @EnableAutoConfiguration ,然后再看源代码,到底自动配置是怎么配置的 ...

  6. Springboot中mybatis执行逻辑源码分析

    Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...

  7. Spring基础系列-AOP源码分析

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9560803.html 一.概述 Spring的两大特性:IOC和AOP. AOP是面向切 ...

  8. 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)

    1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...

  9. spring boot 2.0 源码分析(二)

    在上一章学习了spring boot 2.0启动的大概流程以后,今天我们来深挖一下SpringApplication实例变量的run函数. 先把这段run函数的代码贴出来: /** * Run the ...

随机推荐

  1. 为app录制展示gif

    已同步更新至个人blog:http://dxjia.cn/2015/07/make-gif-for-app/ 在github上好多不错的开源项目展示demo的时候,都是采用了一个gif图片,很生动具体 ...

  2. 第三百九十三节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置

    第三百九十三节,Django+Xadmin打造上线标准的在线教育平台—Xadmin后台进阶开发配置 设置后台某个字段的排序规则 在当前APP里的adminx.py文件里的数据表管理器里设置 order ...

  3. (原)阅读Android-Camera2Video的demo源码和调试心得

    转载请注明出处:http://www.cnblogs.com/lihaiping/p/6142512.html   最近因为项目需要使用到camera的功能,所以针对官方的demo源码进行一番阅读,并 ...

  4. Android开发训练之第五章第六节——Transferring Data Using Sync Adapters

    Transferring Data Using Sync Adapters GET STARTED DEPENDENCIES AND PREREQUISITES Android 2.1 (API Le ...

  5. H5网页适配 iPhoneX,就是这么简单(转)

    iPhoneX 取消了物理按键,改成底部小黑条,这一改动导致网页出现了比较尴尬的屏幕适配问题.对于网页而言,顶部(刘海部位)的适配问题浏览器已经做了处理,所以我们只需要关注底部与小黑条的适配问题即可( ...

  6. Dockerfile编写的注意事项

    一.Dockerfile合理分层 Dockerfile的写法不合理,有时候会导致镜像膨胀,由于Docker是分层设计,而在Dockerfile中,每一条指令都拥有自己的context,而执行到下一条指 ...

  7. 6 CLR静态构造器

    CLR保证一个类型构造器在每个AppDomain中只执行一次,而且这种执行是线程安全的. 作用: 就是初始化静态成员 比如有几个静态成员需要初始化那你把初始化代码放到哪呢? 放到普通构造函数里,那肯定 ...

  8. wchar_t和char转化

    char* WcharToChar(const wchar_t* wp) { char *m_char; int len = WideCharToMultiByte(CP_ACP, 0, wp, wc ...

  9. G - Rabbit and Grass

    大学时光是浪漫的,女生是浪漫的,圣诞更是浪漫的,但是Rabbit和Grass这两个大学女生在今年的圣诞节却表现得一点都不浪漫:不去逛商场,不去逛公园,不去和AC男约会,两个人竟然猫在寝食下棋-- 说是 ...

  10. C# MVC+EF—页面搭建

    上一篇文章搭建了基本结构,现在来搭建页面 一.新建控制器 Controllers=>添加=>控制器=>MVC 5控制器=>命名为DepartmentController pub ...