Возможно ли использовать unproxy a Spring bean?
У меня есть Spring bean, скажем:
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class AImpl implements A {
public void setSomeDependency(D dependency) {
// This setter DOES NOT BELONG to interface A
}
}
<bean id="aImpl" class="AImpl"/>
Теперь я хочу, чтобы интеграция протестировала его, но сначала мне нужно высмеять зависимость D
, потому что это слишком много. Поскольку AImpl
реализует интерфейс и содержит транзакционную аннотацию, сгенерированный прокси совместим только с интерфейсом A
, поэтому я могу это сделать:
@Inject @Named("aImpl")
private A a;
но не может:
@Inject @Named("aImpl")
private AImpl a;
В результате я не могу издеваться над своей зависимостью.
Обратите внимание, что добавление void setSomeDependency(D dependency)
в интерфейс A
не является опцией, поскольку оно не имеет никакого коммерческого значения. Он также использует proxy-target-class="true"
, поскольку он разбивает много других beans (этот атрибут влияет на все beans в контексте).
Есть ли способ отключить введенный bean A
, поэтому я мог бы применить его к AImpl
?
Ответы
Ответ 1
Попробуйте следующее:
if(AopUtils.isAopProxy(a) && a instanceof Advised) {
Object target = ((Advised)a).getTargetSource().getTarget();
AImpl ai = (AImpl)target;
}
Бонус: в Scala Я использую следующую эквивалентную функцию для той же цели:
def unwrapProxy(a: AnyRef) = a match {
case advised: Advised if(AopUtils.isAopProxy(advised)) =>
advised.getTargetSource.getTarget
case notProxy => notProxy
}
Ответ 2
С введением Spring 4.2.RC1 в модуле spring-test
есть выделенный класс утилиты, который обрабатывает этот случай для вас.
Класс называется AopTestUtils
и предоставляет методы:
-
getTargetObject
(разворачивает только прокси верхнего уровня)
-
getUltimateTargetObject
(разворачивает несколько уровней прокси, если они существуют).
Просмотрите соответствующий commit, а также соответствующую проблему.