2011-11-14 33 views
15

que tienen un grano de primavera, digamos:¿Es posible desprogramar un 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"/> 

Ahora quiero poner a prueba la integración, pero primero tengo que burlarse de la dependencia D, porque hace demasiado material. Desde el AImpl implementa una interfaz y contiene una anotación de transacciones, el proxy generada sólo es compatible con la interfaz A, por lo que se puede hacer esto:

@Inject @Named("aImpl") 
private A a; 

pero no puede:

@Inject @Named("aImpl") 
private AImpl a; 

Como resultado, No puedo burlarme de mi dependencia.

Tenga en cuenta que agregar void setSomeDependency(D dependency) a la interfaz A no es una opción, ya que no tiene ningún significado comercial. Tampoco está usando proxy-target-class="true", ya que rompe una gran cantidad de otros beans (este atributo afecta a todos los beans en el contexto).

¿Hay alguna manera de desprogramar el bean inyectado A, por lo que podría convertirlo en AImpl?

+0

posible duplicado de [Lanzar un objeto Proxy de Spring a la clase de tiempo de ejecución real] (http://stackoverflow.com/questions/5976247/casting-a-springs-proxy-object-to-the-actual-runtime-class) – skaffman

+0

@skaffman: gracias por señalarlo, agregué esa pregunta a Spring Tag Preguntas frecuentes –

Respuesta

22

Prueba esto:

if(AopUtils.isAopProxy(a) && a instanceof Advised) { 
    Object target = ((Advised)a).getTargetSource().getTarget(); 
    AImpl ai = (AImpl)target; 
} 

Bono: en Scala estoy usando la siguiente función equivalente para el mismo fin:

def unwrapProxy(a: AnyRef) = a match { 
    case advised: Advised if(AopUtils.isAopProxy(advised)) => 
          advised.getTargetSource.getTarget 
    case notProxy => notProxy 
} 
+8

Gracias, realmente me salvaste. Por cierto, acabo de visitar Oslo por primera vez, ahora no me pregunto por qué pasas tanto tiempo en SO (sin ánimo de ofender, pero el clima no es alentador) :) – MaDa

+2

Me alegro de poder ayudar. Me gustó tanto su comentario que incluso lo cité en mi página de perfil ;-). –

8

Con la introducción de la primavera 4.2.RC1, no hay ahora una clase de utilidad dedicada en el módulo spring-test que maneja este caso por usted.

La clase se llama AopTestUtils y proporciona los métodos:

  • getTargetObject (desenvuelve solamente el proxy de nivel superior)
  • getUltimateTargetObject (desenvuelve múltiples niveles de proxies si existen).

Mira la correspondiente commit así como la respectiva issue.

Cuestiones relacionadas