spring 自定义事物同步器(一): TransactionSynchronizationManager 解析
一、.JPA 获取 Hibernate的session
try {
session = entityManager.unwrap(Session.class);
} catch (Exception e) {// from transactionTemplate?
//throw new IllegalStateException("No transactional EntityManager available");
EntityManagerFactory entityManagerFactory = jpaTransactionManager.getEntityManagerFactory();
EntityManagerHolder holder;
if(TransactionSynchronizationManager.hasResource(entityManagerFactory)){
holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory);
}else{
holder = new EntityManagerHolder(entityManagerFactory.createEntityManager());
TransactionSynchronizationManager.bindResource(entityManagerFactory, holder);
}
session = holder.getEntityManager().unwrap(Session.class);
}
二、TransactionSynchronizationManager.getResource()
/**
* Retrieve a resource for the given key that is bound to the current thread.
* @param key the key to check (usually the resource factory)
* @return a value bound to the current thread (usually the active
* resource object), or {@code null} if none
* @see ResourceTransactionManager#getResourceFactory()
*/
public static Object getResource(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
三、TransactionSynchronizationUtils.unwrapResourceIfNecessary(key)
/**
* Unwrap the given resource handle if necessary; otherwise return
* the given handle as-is.
* @see org.springframework.core.InfrastructureProxy#getWrappedObject()
*/
static Object unwrapResourceIfNecessary(Object resource) {
Assert.notNull(resource, "Resource must not be null");
Object resourceRef = resource;
// unwrap infrastructure proxy
if (resourceRef instanceof InfrastructureProxy) {
resourceRef = ((InfrastructureProxy) resourceRef).getWrappedObject();
}
if (aopAvailable) {
// now unwrap scoped proxy
resourceRef = ScopedProxyUnwrapper.unwrapIfNecessary(resourceRef);
}
return resourceRef;
}
四、ScopedProxy
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/> <bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
In the preceding example, the singleton bean userManager is injected with a reference to the HTTP Session-scoped bean userPreferences. The salient point here is that the userManager bean is a singleton: it will be instantiated exactly once per container, and its dependencies (in this case only one, the userPreferences bean) are also injected only once. This means that the userManager bean will only operate on the exact same userPreferences object, that is, the one that it was originally injected with.
This is not the behavior you want when injecting a shorter-lived scoped bean into a longer-lived scoped bean, for example injecting an HTTP Session-scoped collaborating bean as a dependency into singleton bean. Rather, you need a single userManager object, and for the lifetime of an HTTP Session, you need a userPreferences object that is specific to said HTTP Session. Thus the container creates an object that exposes the exact same public interface as the UserPreferences class (ideally an object that is a UserPreferences instance) which can fetch the realUserPreferences object from the scoping mechanism (HTTP request, Session, etc.). The container injects this proxy object into the userManagerbean, which is unaware that this UserPreferences reference is a proxy. In this example, when a UserManager instance invokes a method on the dependency-injected UserPreferences object, it actually is invoking a method on the proxy. The proxy then fetches the real UserPreferences object from (in this case) the HTTP Session, and delegates the method invocation onto the retrieved real UserPreferences object.
引用:spring docs
五、InfrastructureProxy 结构代理
Interface to be implemented by transparent resource proxies that need to be considered as equal to the underlying resource,
for example for consistent lookup key comparisons. Note that this interface does imply such special semantics and does not
constitute a general-purpose mixin!
Such wrappers will automatically be unwrapped for key comparisons in TransactionSynchronizationManager. Only fully transparent
proxies, e.g. for redirection or service lookups, are supposed to implement this interface. Proxies that decorate the target object
with new behavior, such as AOP proxies, do not qualify here!
被认为等同于底层资源的透明资源代理要实现的接口,例如用于一致的查找的关键字比较。注意,这个接口意味着这样的特殊语义,并不构成一般用途的聚合!
这种包装器将在TransactionSynchronizationManager中自动被拆箱来进行关键字比较。只有完全透明的代理,例如 对于重定向或服务查找,应该实现此接口。
使用新行为来装饰目标对象的代理(例如AOP代理)不适用于此处!
spring 自定义事物同步器(一): TransactionSynchronizationManager 解析的更多相关文章
- spring自定义事务同步器(二):借助redisson实现自己的同步器
1. 借助redis的java客户端redisson实现自己的事物同步器 @Override public void lockWithinCurrentTransaction(Object key) ...
- [转载]开发 Spring 自定义视图和视图解析器
原文出处 http://www.ibm.com/developerworks/cn/java/j-lo-springview/ 概述 Spring 3.0 默认包含了多种视图和视图解析器,比如 JSP ...
- 这一次搞懂Spring自定义标签以及注解解析原理
前言 在上一篇文章中分析了Spring是如何解析默认标签的,并封装为BeanDefinition注册到缓存中,这一篇就来看看对于像context这种自定义标签是如何解析的.同时我们常用的注解如:@Se ...
- Spring源码-IOC部分-自定义IOC容器及Bean解析注册【4】
实验环境:spring-framework-5.0.2.jdk8.gradle4.3.1 Spring源码-IOC部分-容器简介[1] Spring源码-IOC部分-容器初始化过程[2] Spring ...
- spring 自定义解析类
设计配置属性和JavaBean 编写XSD文件 编写NamespaceHandler和BeanDefinitionParser完成解析工作 编写spring.handlers和spring.schem ...
- spring的事物实现
Spring的事物主要有三个接口 PlatformTransactionManager. 根据TransactionDefinition配置的事物信息创建事物 TransactionDefinitio ...
- Spring自定义类扫描器 ClassPathScanningCandidateComponentProvider
项目中有个需求 读取xml文件,然后 对xml文件进行解析,比如如果是 Gender=0/1的话,分别代表男女. 所以需要在构造函数之后,初始化bean之前进行过滤解析 xml文件: <inte ...
- spring 自定义标签的实现
在我们进行Spring 框架开发中,估计用到最多的就是bean 标签吧,其实在Spring中像<mvc/><context/>这类标签以及在dubbo配置的标签都是属于自定义的 ...
- spring基础---->spring自定义初始化(二)
这里新增了对ref属性的支持,并且过滤了已经解析的元素.人生有两个词很棒,一言不合和不提也罢. spring自定义对ref属性支持 项目的结构如下:新增一个ThirdBean类,修改了ParseXml ...
随机推荐
- 二分 + 模拟 - Carries
Carries Problem's Link Mean: 给你n个数,让你计算这n个数两两组合相加的和进位的次数. analyse: 脑洞题. 首先要知道:对于两个数的第k位相加会进位的条件是:a%( ...
- 数学 - Codeforces Round #319 (Div. 1)A. Vasya and Petya's Game
Vasya and Petya's Game Problem's Link Mean: 给定一个n,系统随机选定了一个数x,(1<=x<=n). 你可以询问系统x是否能被y整除,系统会回答 ...
- git 怎么看某个commit 修改的代码
详细的更改: git show commitid 只列出文件名:git show --pretty="format:" --name-only commitid 转自: http: ...
- 手机游戏运营主要的指标是什么? 7天活跃, 14天活跃 ARPU ?如何提升游戏 app 的虚拟道具的收入?
数据采集越细,手段越丰富,所获得的数据也就更加详实,虽然手机游戏没有网游那么复杂,但也需要数据化运营,而且是必要的,是优化游戏收入的关键,大家最主要关心的是下面三类数据的指标 1. 用户数量首先,在移 ...
- Socket长连接和短连接的区别
https://blog.csdn.net/jasonjwl/article/details/52085264 短连接 连接->传输数据->关闭连接 HTTP是无状态的,浏览器和服务器每进 ...
- iOS开发之--如何使用自定义字体
一.首先把字体导入到工程中 二.选择Build Phases -->Copy Boundle Resources ,把所用的字体添加进去,一般x-code会自定导入 三.在info.plist中 ...
- myForm.js
根据控件名,重现一些特殊的表单项,生成html var can_submit = true; function myForm($form_id, $id_value, province, city, ...
- 解决 Unable to load native-hadoop library for your platform
安装hadoop启动之后总有警告:Unable to load native-hadoop library for your platform... using builtin-java classe ...
- 构建API
前言 过程,如图: 第一步创建一个帮助类,类里面提供了加密.组装Url等方法,代码如下: using System; using System.Collections.Generic; using S ...
- 【BZOJ1217】[HNOI2003]消防局的设立 树形DP
[BZOJ1217][HNOI2003]消防局的设立 Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地, ...