En las versiones 1.x de Spring para escribir un aspecto, había que implementar el interface MethodInterceptor de Aop Alliance. Una de las novedades en Spring 2.0 es la integración con AspectJ para expresar los pointcuts y para escribir aspectos basados en POJOs.
Al implementar un POJO no hace falta heredar de ninguna clase ni implementar interface alguno, eso es lo que hace a los POJOs verdaderamente potentes, ya que la verdadera utilidad del POJO se define, bien mediante una anotación o un XML.
Como lasterra se quejaba en el anterior post, que no estaría mal ver ejemplos, pues ahí van unos ejemplos.
En un post anterior, tenía una clase de Servicio Mock que es la que usaré ahora para los ejemplos:
public class MockService{
|
Pues ahora vamos a hacer unas virguerias con la clase y voy a añadir tres tipos de aspectos:
<bean id="mockService"
class="org.dahernan.service.MockService"/>
<bean id="pojoBeforeAspect"
class="org.dahernan.aspects.PojoBeforeAspect"/>
<bean id="pojoAfterAspect"
class="org.dahernan.aspects.PojoAfterAspect"/>
<bean id="pojoAroundAspect"
class="org.dahernan.aspects.PojoAroundAspect"/>
Vamos a por el más sencillo, el aspecto Before. Implementamos una simple clase que loggea el servicio.
public class PojoBeforeAspect {
|
Una vez que se tiene la clase se define el aspecto en el XML (yo prefiero el XML que la anotación, cuestión de gustos).
<aop:aspect id="beforeAspect" ref="pojoBeforeAspect">
<aop:advice
pointcut="execution(* org.dahernan..*MockService.getPedido(..)) and args(idPedido)"
method="log"
kind="before"
/>
</aop:aspect>
Se ve en el XML que se define un aspecto, y se pone como referencia el id del POJO "pojoBeforeAspect", se especifica que es un aspecto del tipo before (kind="before"). Se especifica también que el método que tiene que ejecutar del POJO es el método "log" (method="log"). Y lo más importante se define el pointcut mediante la expresión "execution". Traducida un poco significa, que me intercepte el método "getPedido" de la clase "MockService" y que además enlace el primer argumento del método "getPedido", con el argumento idPedido del método "log" del POJO. Con lo que el método "log" del POJO recibirá lo que se le pase a getPedido.
Esto está realmente bien, ya que no hay que hacer los típicos casting de objetos. Ya se preocupa el framework de interceptar sólo los métodos que coincidan con los tipos que se definen.
Vamos a ver ahora el aspecto After, donde hay alguna novedad.
public class PojoAfterAspect {
|
Bueno es muy parecida a la de Before, lo que pasa es que le añado el parámetro JoinPoint, es opcional en todos los aspectos que definas y permite acceder a información del método que se intercepta (la signature por ejemplo). Como en el caso anterior ahí va el XML para la definición del aspecto.
<aop:aspect id="afterAspect" ref="pojoAfterAspect">
<aop:advice
pointcut="execution(* org.dahernan..*MockService.getPedido(..))"
returning="pedido"
method="logResult"
kind="afterReturning"
/>
</aop:aspect>
Lo que cambia con respecto al anterior es el atributo returning="pedido", que hace que se enlace el objeto que retorna el método "getPedido" con el argumento "pedido" del método "logResult", de la implementación del PojoAfterAspect. Una vez más no hace falta implementar ningún interface, ni hacer cast.
Por último el aspecto más complicado, el Around. Este aspecto obliga a que el primer argumento del método del aspecto sea del tipo ProceedingJoinPoint, esto es para poder controlar cuando se invoca al método interceptado. Además he mezclado un poco con la definición de los dos aspectos anteriores (para hacerlo más interesante).
public class PojoAroundAspect {
|
En este caso si hay que hacer un pequeño cast, porque el método "proceed", devuelve un Object. Sin embargo, por la propia definición del pointcut nunca nos va a dar un ClassCastException.
<aop:aspect id="aroundAspect" ref="pojoAroundAspect">
<aop:advice
pointcut="execution(* org.dahernan..*MockService.getPedido(..)) and args(id)"
method="aroundMethod"
kind="around"
/>
</aop:aspect>
Tanto la definición del aspecto como la del pointcut es muy parecida a las anteriores y mezcla algunas características como la captura de los argumentos.
Nada más y nada menos por hoy.
Enviado por dahernan ( jun 03 2006, 05:54:38 PM CEST )
Permalink | Comentarios [6] | Agregar a del.icio.us
Gracias por el ejemplo ;-) El 2004 seguramente fue el año del AOP, hacia tiempo que no leia nada sobre esto... se usa?? es un recurso más o es algo que realemente todo programador debería conocer?
Enviado por Enrique Rodriguez en junio 05, 2006 a las 01:28 AM CEST #
Yo lo uso y mucho, principalmente para el cacheo de objetos y manejo de transacciones, un poco para log y tambien he usado Acegi para la seguridad.
Son soluciones muy buenas, por ejemplo la del cacheo es una clase de apenas 100 lineas, que soluciona un moton de casos de cacheo, no me imagino tener que meter codigo de cacheo por el medio de las clases.
Son esas cosas que hasta que no lo tienes no lo hechas de menos.
Enviado por dahernan en junio 05, 2006 a las 09:06 AM CEST #
Muy bueno el ejemplo.
Parece que es muy util para quitar poner trazas en tiempo de ejecucion.
Parece que AspectJ es la especificacion que se esta comiendo el mercado.
La AOP esta muy bien para todos los llamadas servicios transversales de las aplicaciones.
Hoy puedes hacer log, mañana persistencia, ...
Sigue flojo el tema de los XML y las anotaciones. Pero es el mal de Java.
Enviado por batch4j en junio 05, 2006 a las 03:54 PM CEST #
lo felicito es usted muy inteligente gracias por la informacion jehova lo bendiga
Enviado por 201.228.120.139 en septiembre 04, 2006 a las 08:20 PM CEST #
Muy interesante el tema de AOP con Spring , he realizado los demos y me han funcionado correctamente, pero tengo una duda; aqui estoy definiendo el bean "MockService" dentro de spring , pero que pasa si necesito interceptar varios metodos de varias clases que no necesariamente estaran definidas como beans de spring, el tipo ejemplo de logging, como lo podria hacer ????
Enviado por Henry Molina en octubre 11, 2006 a las 04:20 AM CEST #
hola, con Spring 2.0 segun tengo entendido puedes interceptar cualquier clase aunque no este definido como bean de spring (no lo he probado aun), habria que mirar la documentacion
Enviado por dahernan en octubre 18, 2006 a las 08:25 PM CEST #