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 userManager
bean, 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 ...
随机推荐
- xcode6 dyld_sim is not owned by root
如果运行复制过来的xcode可能会这个提示,xcode6 dyld_sim is not owned by root解决方法打开终端 输入sudo xcode-select -switch /Appl ...
- JavaScript概述.pdf
第1章 JavaScript概述 第2章 使用JavaScript 第3章 语法.关键保留字及变量 第4章 数据类型 第5章 运算符 第6章 流程控制语句 第7章 函数 //没有参数的函数 funct ...
- 记一次redis攻击
服务器挖矿病毒的排查过程 事情起因:朋友的一台阿里云主机,登录特别卡,找我看看 这一看就感觉出问题了,机器特别卡,top看了一眼,cpu几乎是100%运行 但是奇怪的是用top命令完全看不出来哪个进程 ...
- mongdb 慢查询
查看mongodb慢查询 赶紧打开服务器爸爸,开慢查询,看下耗时500ms以上的都是些啥: db.setProfilingLevel(2,500) 看下最近的10条具体的慢查询指令: db.syste ...
- sqlServer的主键只能自增不能手动增加
1. 2.找到相应的表,找到表设计.
- easyui_extension.js
$.extend($.fn.datagrid.methods,{ /** * 开打提示功能 * * @param {} * jq * @param {} * params 提示消息框的样式 * @re ...
- 第二百七十二节,Tornado框架-iframe标签框架伪造ajax
Tornado框架-iframe标签框架伪造ajax html <!DOCTYPE html> <html> <head lang="en"> ...
- 【Debian】ftp安装
http://www.2cto.com/os/201107/98311.html http://jingyan.baidu.com/article/adc815133476bdf723bf7393.h ...
- Angular ContentChild
contentchild // 使用方法 git clone https://git.oschina.net/mumu-osc/learn-component.git cd learn-compone ...
- UnboundLocalError: local variable 'merchantCode' referenced before assignment
问题描述:变量赋值前未定义 定位原因:变量没有结果返回,导致赋值失败