OpenSessionInViewFilter——>TransactionSynchronizationManager

4961 ワード

public abstract class TransactionSynchronizationManager {

TransactionSynchronizationManagerは、同期が必要なトランザクションリソースを管理したり、スレッドを管理したりして、現在のスレッドにリソースをバインドすることができます.
次に、TransactionSynchronizationManagerクラスのいくつかの重要な方法について説明します.
	public static boolean hasResource(Object key) {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doGetResource(actualKey);
		return (value != null);
	}
上の方法では現在のスレッドでsessionが見つかるかどうかを判断し、
現在のスレッドがセッションにバインドされているかどうかを判断します.keyはセッションファクトリオブジェクトで、セッションファクトリはセッションをバインドできます.
TransactionSynchronizationUtilsツールクラスのunwrapResourceIfNecessary()メソッドは、パッケージを解除する方法です.パッケージされたクラスが投げ込まれると元のクラスに戻り、パッケージされていないクラスに送られると、戻ってくるのはそれ自身、つまりsessionFactoryに送られ、戻ってくるのはsessionFactoryです.
	public static void bindResource(Object key, Object value) throws IllegalStateException {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Assert.notNull(value, "Value must not be null");
		Map<Object, Object> map = resources.get();
		// set ThreadLocal Map if none found
		if (map == null) {
			map = new HashMap<Object, Object>();
			resources.set(map);
		}// Map
		Object oldValue = map.put(actualKey, value);
		// Transparently suppress a ResourceHolder that was marked as void...
		if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
			oldValue = null;
		}
            .............................. 
}

ここのbindResourceの方法は
セッションを現在のスレッドにバインドします.ここでresoucesはT r a n s c t ionSynchronizationManagerの属性の一つです.以下のようにThreadLocalクラスで、中の汎用TはMapがThreadLocalに伝わります.TransactionSynchronizationManagerクラスには、ThreadLocal、ThreadLocalなど、いくつかのThreadLocalクラスがあります.
	private static final ThreadLocal<Map<Object, Object>> resources =
			new NamedThreadLocal<Map<Object, Object>>("Transactional resources");
public class ThreadLocal<T> {
public class NamedThreadLocal<T> extends ThreadLocal<T> {
ここThreadLocalとNamedThreadLocalは大体同じですが、
NamedThreadLocalは名前で作成できます.
ThreadLocalクラスに来ました
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

ここはちょっとわかりにくいですが、
TransactionSynchronizationManagerではTつまりmapが入ってきます.つまりThreadLocalに相当します.createMapメソッドでは現在のスレッドtとT(Map)が入ってきます.
t.threadLocals=new ThreadLocalMap(this,firstValue); ここのthisはこのクラス自体ThreadLocal、firstValueは伝わってきたMapで、次の表はt.threadLocalsで、keyはクラス自体で、valueはT(つまりmap)、あなたが伝わってきたTは何で、valueは何ですか.ここでThreadLocalつまりThreadLocal>
ThreadLocal
Map
ThreadLocal
List
ThreadLocal
String
ThreadLocal
Boolean
これらはすべてthreadLocalsの中に入っています
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);// key, value(Map<Object,Object>,List<Object>)
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }
   ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
だから上に見える
TransactionSynchronizationManagerでresouces.get()が得たのは転送されたMapですが、現在のこのMapはスレッドにバインドされているMapです.
Object oldValue = map.put(actualKey, value);ここではSessionFactoryとnew new SessionHolder(Session)をMapに入れて、ここもスレッドにバインドしました.以上のコードはスレッドにバインドされています.
次は解縛です.
	public static Object unbindResource(Object key) throws IllegalStateException {
		Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
		Object value = doUnbindResource(actualKey);
		if (value == null) {
			throw new IllegalStateException(
					"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
		}
		return value;
	}

unbindResourceメソッドでは、このセッションファクトリーに対応するセッションをスレッドから削除します.つまり、t.threadLocalsというMapからThreadLocalを削除します.このThreadLocalにはセッションファクトリーとセッションが格納されており、ThreadLocalを削除することで、セッションを削除することになります.doUnbindResource(Object actualKey)を表示できます.中はセッションを先に除去し,削除スレッドからThreadLocalを除去する.