Приведение объекта Proxy Spring к фактическому классу времени выполнения
Я использую Spring, в какой-то момент я хотел бы привести объект к его фактической реализации во время выполнения.
Пример:
Class MyClass extends NotMyClass {
InterfaceA a;
InterfaceA getA() { return a; }
myMethod(SomeObject o) { ((ImplementationOfA) getA()).methodA(o.getProperty()); }
}
Это кричит ClassCastException
поскольку a
это $ProxyN
объект. Хотя в beans.xml я ввел бин, который принадлежит к классу ImplementationOfA
,
РЕДАКТИРОВАТЬ 1 Я расширил класс, и мне нужно вызвать метод в ImplementationOfA
, Поэтому я думаю, что мне нужно сыграть. Метод получает параметр.
РЕДАКТИРОВАТЬ 2
Я лучше оторву целевой класс:
private T getTargetObject(Object proxy, Class targetClass) throws Exception {
while( (AopUtils.isJdkDynamicProxy(proxy))) {
return (T) getTargetObject(((Advised)proxy).getTargetSource().getTarget(), targetClass);
}
return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class
}
Я знаю, что это не очень элегантно, но работает.
Все кредиты на http://www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/ Спасибо!
3 ответа
Зачем тебе кастовать? Об использовании Spring прокси это отличная статья, я предлагаю вам прочитать ее, а также комментарии.
А также раздел прокси (7.1.3) из документации Spring AOP.
Теперь вы можете использовать
AopTestUtils.getTargetObject(proxy)
.Реализация аналогична предложению @siulkilulki, но используется помощник Spring
Для меня версия от EDIT 2 не работала. Ниже один работал:
@SuppressWarnings({"unchecked"})
protected <T> T getTargetObject(Object proxy) throws Exception {
while( (AopUtils.isJdkDynamicProxy(proxy))) {
return (T) getTargetObject(((Advised)proxy).getTargetSource().getTarget());
}
return (T) proxy; // expected to be cglib proxy then, which is simply a specialized class
}
Использование:
UserServicesImpl serviceImpl = getTargetObject(serviceProxy);
serviceImpl.setUserDao(userDAO);
В основном, когда вы используете AOP в Spring, Spring создает Proxy для вас. У вас есть два варианта:
- когда вы применяете аспект к бину, который реализует интерфейс, в этом случае Spring использует JdkDynamicProxy
- если ваш bean-компонент Spring не реализует никакого интерфейса и если у вас есть cglib 2.2 в вашем classpath, учтите, что начиная с весны 3.2.x у вас есть cglib в контейнере Spring по умолчанию, sprirng использует специальный прокси-сервер, называемый CGLibProxy.
Ключевым моментом является то, что при применении аспекта к вашему бобу Spring создаст прокси, и если вы попытаетесь выполнить приведение, вы получите исключение.
Я надеюсь, что это может помочь вам