Как захватить Callable и выполнить скрытые методы перед вызовом ()
Я добавляю реализации к некоторым подсистемам в более крупном проекте (HypergraphDB), и мне следует избегать изменения важного кода. В этом проекте есть около 70 вызываемых объектов, которые определяют блоки транзакций для некоторых операций базы данных. Я заменяю эту базу данных, и моему (redis) нужны все затронутые ключи перед определением блока транзакции. Поэтому мне нужно получить доступ к частям в этих Callables и выполнить что-то ("смотреть") непосредственно перед выполнением call().
Некоторые из Callables нетривиальны, и для некоторых из них мне нужно было бы объявить конечные поля в этом 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() {.........
Интерфейс Handable:
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 ответ
Если вы действительно хотите перехватить 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);
}
}