bean proxy con ámbito de primavera

98

¿Alguien puede explicar el uso de la @ScopedProxyanotación de primavera ? Yo pensaba que tenía algo que ver con los beans de sesión con ámbito, pero no estoy muy seguro de qué.

En mi uso de ámbitos, he usado beans con ámbito de sesión sin la @ScopedProxyanotación (o sin proxies con ámbito aop), así que estoy realmente seguro de cómo usarlo correctamente.

Jeff Storey
fuente
consulte la documentación del bean . La sesión es uno de los ámbitos , pero no el único.
Gus
1
@Gus, soy consciente de los alcances, pero no estoy seguro de cómo juega el proxy con alcance en eso
Jeff Storey
1
En mi opinión, la sección 3.4.4.5 es una explicación bastante buena de lo que hace un proxy con ámbito. - el bit entre los dos ejemplos es la parte importante.
Gus
2
Sí, eso lo explica, gracias. Si desea agregar una respuesta a la pregunta, la acepto.
Jeff Storey

Respuestas:

248

La sección 3.4.4.5 de los documentos de primavera lo explica bastante bien:

(tenga en cuenta que la siguiente definición de bean 'userPreferences' tal como está está incompleta):

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>

A partir de la configuración anterior, es evidente que el bean singleton 'userManager' se está inyectando con una referencia al bean de ámbito de sesión HTTP 'userPreferences'. El punto destacado aquí es que el bean 'userManager' es un singleton ... se instanciará exactamente una vez por contenedor , y sus dependencias (en este caso solo una, el bean 'userPreferences') también solo se inyectarán (¡una vez! ) .

Esto significa que el 'userManager' (conceptualmente) solo operará en el mismo objeto 'userPreferences', que es el que se inyectó originalmente.

Esto no es lo que desea cuando inyecta un bean de ámbito de sesión HTTP como una dependencia en un objeto colaborador (normalmente). Más bien, lo que queremos es un único objeto 'userManager' por contenedor , y luego, durante la vida útil de una sesión HTTP, queremos ver y usar un objeto 'userPreferences' que sea específico de dicha sesión HTTP .

Más bien, lo que necesita es inyectar algún tipo de objeto que exponga exactamente la misma interfaz pública que la clase UserPreferences (idealmente un objeto que sea una instancia de UserPreferences) y que sea lo suficientemente inteligente como para poder ir y buscar el objeto UserPreferences real desde cualquier mecanismo de alcance subyacente que hayamos elegido (solicitud HTTP, sesión, etc.). Luego podemos inyectar de manera segura este objeto proxy en el bean 'userManager', que ignorará felizmente que la referencia de UserPreferences que está sosteniendo es un proxy .

En nuestro caso, cuando una instancia de UserManager invoca un método en el objeto UserPreferences inyectado en dependencia, realmente invocará un método en el proxy ... el proxy se apagará y buscará el objeto UserPreferences real de (en este caso) la sesión HTTP y delegar la invocación del método en el objeto UserPreferences real recuperado.

Es por eso que necesita la siguiente configuración, correcta y completa, al inyectar beans con ámbito de solicitud, sesión y sesión global en objetos de colaboración:

<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
    <aop:scoped-proxy/>
</bean>

<bean id="userManager" class="com.foo.UserManager">
    <property name="userPreferences" ref="userPreferences"/>
</bean>
Gus
fuente
Entonces, cuando uso la anotación @ScopedProxy, se usará un Proxy automáticamente, ¿y esto es todo? ScopedProxy significa -> No use esta clase como está, use un Proxy para ella?
Koray Tugay
3
Estoy usando spring-web: 4.3.3 y parece que la anotación @ScopedProxyfue reemplazada por @RequestScopey otras. Puede encontrar ejemplos aquí: logicbig.com/tutorials/spring-framework/spring-core/…
adebasi
1
Podríamos decir que cuando @Scope(value="session", proxyMode = ScopedProxyMode.TARGET_CLASS)se usa la notación , SpringMVC no usa WebApplicationContext para Autowired, sino que usa CGLIB para crear el proxy. Aquí otra explicación con ejemplos fuera
Kurapika
0

Después de probar varias opciones diferentes especificadas aquí y la documentación de Spring, he descubierto por alguna razón que Spring MVC es un controlador de cableado automático extraño cuando usa la anotación @Controller y donde tiene más de un controlador de este tipo en su aplicación web. Modificada la anotación a @RestController (valor = "UniqueControllerv1"), el problema está resuelto.

geeksquad87
fuente