как захватить Callable и выполнить скрытые методы перед вызовом () - PullRequest
1 голос
/ 29 июня 2011

Я добавляю реализации к некоторым подсистемам в более крупном проекте (HypergraphDB), и мне следует избегать изменения важного кода.В этом проекте есть около 70 вызываемых объектов, которые определяют блоки транзакций для некоторых операций базы данных.Я заменяю эту базу данных, и моему (redis) нужны все затронутые ключи перед определением блока транзакции.Поэтому мне нужно получить доступ к частям в этих Callables и выполнить что-то («наблюдать») непосредственно перед выполнением call ().

Некоторые из Callables нетривиальны, и для некоторых из них мне нужно объявить finalПоля в этом Callable, и они определены "за пределами" вызова, поэтому оба 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();

1 Ответ

1 голос
/ 29 июня 2011

Если вы действительно хотите перехватить Callables, а не изменять существующий код, тогда лучше всего поменять местами другую реализацию при вызове getTransactionManager (), поскольку именно там вы передаете свои Callables.

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

}

...