2012-05-10 11 views
9

Estoy utilizando Spring 3 AOP, y tengo un aspecto que requiere acceso a HttpServletRequest. Se ve algo como esto:Spring AOP y seguridad de hilos de aspecto para un HTTPServletRequest bean autoalineado

@Aspect 
public class MyAspect { 

    @Autowired 
    private HttpServletRequest httpServletRequest; 

    public void init() { 
     // Do something once... 
    } 

    @Before("my pointcut here...") 
    private void myMethod() { 
     // I need the httpServletRequest... 
    } 

    @After("my pointcut here...") 
    private void myOtherMethod() { 
     // I need the httpServletRequest... 
    } 
} 

Y está configurado de esta manera:

<bean id="myAspect" class="com.some.package.MyAspect" init-method="init" /> 

es el método init sólo se llama una vez por contenedor IoC, a pesar de que este es un aspecto, y están a salvo el hilo HTTPServletRequest ? Si no es así, ¿cuál es la mejor manera de obtenerlo durante la ejecución del consejo y que sea seguro para subprocesos? Si es posible, prefiero no usar un hilo local.

Respuesta

16

es el método init sólo se llama una vez al COI contenedor

Se llama una vez por cada instancia del bean. Si bean tiene un alcance singleton (que también es el caso predeterminado para los aspectos), solo se llamará una vez. Sin embargo, no tendrá acceso al httpServletRequest dentro del método init() - ¡todavía no hay una solicitud!

es seguro

el hilo HTTPServletRequest no es, pero no se preocupe. Esto es realmente mucho más complejo de lo que parece. Está inyectando una solicitud de servlet HTTP (y obviamente puede haber varias solicitudes disponibles al mismo tiempo) en un objeto singleton. ¿Cuál es inyectado? Ninguno (¿todos?) De ellos! Spring crea un proxy sofisticado (denominado proxy con ámbito) y cada vez que accede a los métodos de inyección de httpServletRequest los delega en actual (para enhebrar) la solicitud. De esta forma, puede ejecutar sus aspectos de forma segura en varios subprocesos: cada uno operará en una solicitud física diferente.

Todo este comportamiento se describe en gran detalle en 4.5.4.5 Scoped beans as dependencies:

[...] Si desea inyección (por ejemplo) una solicitud HTTP con ámbito de frijol en otro grano de, se tiene que inyectar una Proxy de AOP en lugar del bean con ámbito. Es decir, debe inyectar un objeto proxy que exhiba la misma interfaz pública que el objeto con ámbito pero que también pueda recuperar el objeto objetivo real del ámbito relevante (por ejemplo, una solicitud HTTP) y delegar llamadas de método al objeto real .

Sobre ThreadLocal:

que prefieren no utilizar un hilo local.

Afortunadamente - Spring está utilizando uno para usted. Si comprende cómo funciona ThreadLocal, Spring coloca la solicitud actual en un subproceso local y delega a la instancia de subproceso local cuando tiene acceso al proxy httpServletRequest.

+0

Tom, esta es una gran respuesta. ¿Es posible que Spring tenga esto documentado en algún lugar que pueda leer? Fue muy difícil encontrar algo relacionado con el funcionamiento del proxy.Ah, y no necesito acceder a la solicitud desde el init() - eso me hizo trampa y metí dos preguntas en una :) :) –

+0

@BrianReindel: Incluí una referencia a la documentación de Spring en mi respuesta. –

+0

Hola Thomasz, ¿funcionará el código en la respuesta? También puede dar su opinión sobre "http://stackoverflow.com/questions/22923813/set-systems-property-in-controller-and-access-that-in-an-aspect" – riship89

Cuestiones relacionadas