Spring 事务笔记

本文探讨了Spring中的InfrastructureProxy接口,它用于创建透明的资源代理,确保代理对象在关键比较时等同于底层资源。该接口主要用于重定向和服务查找,而非增加目标对象的行为,如AOP代理。TransactionSynchronizationManager在比较时会自动拆箱这些代理。内容还涉及了TransactionSynchronizationUtils和TransactionSynchronizationManager的角色,以及如何在特定条件下透明地移除ResourceHolder。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

代码写着写着就钻进源码了。

概念

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代理)不适用于此处!

也就是相当于对象本身等同于所封装的内部对象。

代码:

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;
}

这个方法在TransactionSynchronizationUtils中。

再看看调用者:TransactionSynchronizationManager

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;
}

private static Object doGetResource(Object actualKey) {
    Map<Object, Object> map = resources.get();
    if (map == null) {
        return null;
    }
    Object value = map.get(actualKey);
    // Transparently remove ResourceHolder that was marked as void...
    if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
        map.remove(actualKey);
        // Remove entire ThreadLocal if empty...
        if (map.isEmpty()) {
            resources.remove();
        }
        value = null;
    }
    return value;
}

resources 就是 NamedThreadLocal,这个不用多说。
如果里面存放的是ResourceHolder并且是Void标记,就透明地移除掉。

调用者是sqlSessionUtils

import static org.springframework.transaction.support.TransactionSynchronizationManager.getResource;


public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
  ....
 SqlSessionHolder holder = (SqlSessionHolder) getResource(sessionFactory);
//如果hold已经存在并且不为空。
 if (holder != null && holder.isSynchronizedWithTransaction()) {
   if (holder.getExecutorType() != executorType) {
     throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");
   }
   //直接返回
   return holder.getSqlSession();
 }
//打开Session
 SqlSession session = sessionFactory.openSession(executorType);
.....
 if (isSynchronizationActive()) {
   Environment environment = sessionFactory.getConfiguration().getEnvironment();

   if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {

     holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
     bindResource(sessionFactory, holder);//绑定到TransactionSynchronizationManager
     registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
     holder.setSynchronizedWithTransaction(true);//将连接资源标记为已经同步过
     holder.requested();
   } else {
   //如果不是Spring管理的事务,则看看是不是错误得被搞进Spring了。
     if (getResource(environment.getDataSource()) == null) {
       if (logger.isDebugEnabled()) {
         logger.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");
       }
     } else {
       throw new TransientDataAccessResourceException(
           "SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
     }
   }
 } else {
 //同步没有激活,不需要注册到同步事务中
   if (logger.isDebugEnabled()) {
     logger.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
   }
 }

 return session;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值