Я ищу предложения о том, как внедрить зависимости времени выполнения в сущности JPA, полученные из Hibernate. Моя проблема, по сути, такова:
У меня есть несколько различных подклассов объекта транзакции. Каждый подкласс Transaction по-разному ведет себя при выполнении и требует различного набора зависимостей от среды. Эти объекты транзакций управляются как объекты JPA с помощью Hibernate, поэтому я не могу эффективно использовать Guice для внедрения зависимостей, чтобы заполнить экземпляры их зависимостями среды, как я делаю в остальной части моего приложения.
Чтобы обойти эту проблему, я выбрал подход, несколько схожий с шаблоном Visitor, а именно:
public abstract class Transaction {
// ...snip...
public abstract void apply(Transactor transactor);
}
public class TransactionA extends Transaction {
public void apply(Transactor transactor) {
transactor.execute(this);
}
}
public class TransactionB extends Transaction {
public void apply(Transactor transactor) {
transactor.execute(this);
}
}
// other Transaction subclasses with the same boilerplate
public interface Transactor {
public void execute(TransactionA trans);
public void execute(TransactionB trans);
// corresponding methods for other transaction types.
}
public class BeginTransactor {
@Inject
private Foo execAdep;
public void execute(TransactionA trans) {
execAdep.doSomething(...)
}
@Inject
private Bar execBdep;
public void execute(TransactionB trans) {
execBdep.doOther(...)
}
}
У меня есть различные реализации Transactor для разных частей жизненного цикла транзакции. Они могут быть внедрены в зависимости с помощью Guice в контекст, в котором я хочу обрабатывать транзакции, где я просто вызываю:
Transactor transactor = injector.getInstance(BeginTransactor.class); //Guice injection
Transaction t = ... //get a transaction instance
t.apply(transactor);
Что мне не нравится в этом подходе, так это (1) Не каждый тип транзакции должен быть исполняемым на каждой фазе жизненного цикла, но каждый Transactor должен реализовывать метод execute () для каждого подкласса транзакции и (2) по сути, ни один из внедренные зависимости используются для обработки нескольких типов транзакций.
По сути, мой интерфейс и реализации Transactor содержат много несвязанных друг с другом слов. В идеале я бы просто использовал метод execute () для самого объекта транзакции, но я не хочу, чтобы вызывающий код должен был знать о типе транзакции или зависимостях, которые ему требуются. Кроме того, это может усложнить тестирование, потому что я не мог легко смоделировать метод execute (), если бы это был конкретный метод объекта Transaction. Использование интерфейса Transactor означает, что я могу легко смоделировать его при необходимости.
Кто-нибудь может подсказать, как решить эту проблему безопасным для типов способом, который не приводит к тому, что в Transactor смешивается куча в основном несвязанного поведения, но сохраняет тестируемость и позволяет внедрять зависимости?