Приведение объекта 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 для вас. У вас есть два варианта:

  1. когда вы применяете аспект к бину, который реализует интерфейс, в этом случае Spring использует JdkDynamicProxy
  2. если ваш bean-компонент Spring не реализует никакого интерфейса и если у вас есть cglib 2.2 в вашем classpath, учтите, что начиная с весны 3.2.x у вас есть cglib в контейнере Spring по умолчанию, sprirng использует специальный прокси-сервер, называемый CGLibProxy.

Ключевым моментом является то, что при применении аспекта к вашему бобу Spring создаст прокси, и если вы попытаетесь выполнить приведение, вы получите исключение.

Я надеюсь, что это может помочь вам

Другие вопросы по тегам