2011-05-12 16 views
12

Estoy usando Spring, en un punto me gustaría convertir el objeto a su implementación real en tiempo de ejecución.Transmitiendo un objeto Proxy de Spring a la clase de tiempo de ejecución real

Ejemplo:

Class MyClass extends NotMyClass { 
    InterfaceA a; 
    InterfaceA getA() { return a; } 

    myMethod(SomeObject o) { ((ImplementationOfA) getA()).methodA(o.getProperty()); } 
} 

Eso grita un ClassCastException desde a es un objeto de $ProxyN. Aunque en beans.xml inyecté un bean que es de la clase ImplementationOfA.

EDIT 1 me extendió una clase y tengo que llamar a un método en el ImplementationOfA. Entonces creo que necesito lanzar. El método recibe un parámetro.

EDIT 2

Será mejor arranco la clase de destino:

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 
} 

Sé que no es muy elegante, pero funciona.

Todos los créditos a http://www.techper.net/2009/06/05/how-to-acess-target-object-behind-a-spring-proxy/ ¡Gracias!

+1

Esta es una mala práctica, la clase de implementación real no debería ser relevante. Sin embargo, es posible, dependiendo de cómo se crea su proxy. – skaffman

+0

Si necesita llamar a un método en 'ImplementationOfA', entonces agregue ese método a la interfaz' InterfaceA', o defina una segunda interfaz y agregue el método a eso. – skaffman

+0

Bueno, sé que no es ideal, pero la clase que estoy implementando implementa una interfaz, y debido a los requisitos de la aplicación no puedo modificar InterfaceA ni NotMyClass. – ssedano

Respuesta

0

Básicamente, cuando utiliza AOP en Spring, Spring crea un Proxy para usted. Usted tiene dos opciones:

  1. cuando se aplica un aspecto en un bean que implementa una interfaz, en este uso caso primavera JdkDynamicProxy
  2. cuando su grano de resorte no se implementa ninguna interfaz y si tiene cglib 2.2 en su classpath, tenga en cuenta que desde la primavera 3.2.x tiene cglib en el contenedor de resorte de forma predeterminada, usando un proxy especial llamado CGLibProxy.

El punto clave es que si se aplica un aspecto a su bean Spring aplicará un proxy y si trata de realizar un lanzamiento obtendrá una excepción.

espero tha esto puede ayudarle a

4

Para mi versión de EDIT 2 no trabajado. A continuación se trabajó:

@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 
} 

Uso:

UserServicesImpl serviceImpl = getTargetObject(serviceProxy); 
    serviceImpl.setUserDao(userDAO); 
Cuestiones relacionadas