1

より大きなプロジェクト (HypergraphDB) のいくつかのサブシステムに実装を追加していますが、重要なコードを変更することは避ける必要があります。このプロジェクトには、一部のデータベース操作のトランザクション ブロックを定義する約 70 個の Callable オブジェクトがあります。私はそのデータベースを置き換えており、私の (redis) は、トランザクション ブロックを定義する前に、影響を受けるすべてのキーが必要です。そのため、これらの Callables 内のパーツにアクセスし、call() を実行する直前に何か (「ウォッチ」) を実行する必要があります。

一部の Callable は自明ではなく、その一部については、その Callable で final フィールドを宣言し、それらを呼び出しの「外部」で定義する必要があるため、call() と getHandles() の両方がそれらにアクセスできます。

getHandles メソッドにアクセスできるようにするために、getHandles メソッドだけを持つインターフェースを定義しました。getHandles にアクセスするために、Callable をそのインターフェイスに一時的にキャストできます。IDE ではメソッドが「見える」ようになりましたが、テストする手段がありません。

これはうまくいきますか?

前のコード:

       private HGLiveHandle addLink(final Object payload, 
                             final HGHandle typeHandle, 
                             final HGLink outgoingSet, 
                             final byte flags)
{
    return getTransactionManager().ensureTransaction(new Callable<HGLiveHandle>() 
    { public HGLiveHandle call() {
        HGAtomType type = typeSystem.getType(typeHandle);
        HGPersistentHandle pTypeHandle = getPersistentHandle(typeHandle);
        HGPersistentHandle valueHandle = TypeUtils.storeValue(HyperGraph.this, payload, type);            
......
}

後のコード:

         private HGLiveHandle addLink(final Object payload, 
                             final HGHandle typeHandle, 
                             final HGLink outgoingSet, 
                             final byte flags)
{
    return getTransactionManager().ensureTransaction(new Callable<HGLiveHandle>() 
    {

        final HGAtomType type = typeSystem.getType(typeHandle);
        final HGPersistentHandle pTypeHandle = getPersistentHandle(typeHandle);
        final HGPersistentHandle valueHandle = TypeUtils.storeValue(HyperGraph.this, payload, type);

        public HGPersistentHandle[] getHandles() {
               HGPersistentHandle[] result = new HGPersistentHandle[3+outgoingSet.getArity()];
           result[0] = atomHandle.getPersistent();
           result[1] = typeHandle.getPersistent();
           result[2] = valueHandle.getPersistent();
           result[3] = pTypeHandle;
           result[4] = .valueHandle;
           return result;
        }

        public HGLiveHandle call() {.........

扱えるインターフェース:

     public interface Handable {

public HGPersistentHandle[] getHandles();

}

そして最後に、それが呼び出されている場所:

     public <V> V ensureTransaction(Callable<V> transaction, HGTransactionConfig config)
{
    if (getContext().getCurrent() != null)
        try 
        {
            for (HGPersistentHandle ph: ((Handable) transaction).getHandles());
            .... writeJedis.watch(ph.toByteArray);
            return transaction.call();
4

1 に答える 1

1

本当に Callable をインターセプトしたいが、既存のコードを変更したくない場合は、 getTransactionManager() が呼び出されたときに別の実装にスワップするのが最善の策です。

public class MyTransactionManager implements TransactionManager {

private final TransactionManager originalManager = ...;

public <V> V ensureTransaction(Callable<V> transaction, HGTransactionConfig config) {
    // Check for appropriate type
    if( transaction instanceof Handable) {
        for (HGPersistentHandle ph: ((Handable) transaction).getHandles()) {
            writeJedis.watch(ph.toByteArray);
        }
    }
    // Delegate to the original implementation
    return originalManager.ensureTransaction(transaction, config);
}

}

于 2011-06-29T19:07:20.663 に答える