Aspect Oriented Programming introduction

34
1 Chapter 1. Aspect Oriented Programming Table of Contents Motivaciones ................................................................................................................ 1 Evolución de las metodologías de programación ................................................................ 3 AOP en el mundo real ................................................................................................... 4 Hype Cycle .......................................................................................................... 4 ¿Dónde se utiliza AOP? ......................................................................................... 6 Introducción a AOP ...................................................................................................... 7 Metodología AOP ................................................................................................. 7 Anatomía de un lenguaje orientado a aspectos ........................................................... 8 Beneficios de la metodología AOP ........................................................................... 9 Verdades y mentiras sobre AOP ............................................................................ 10 Visión general de AspectJ ............................................................................................. 11 Introducción a AspectJ ......................................................................................... 11 Modelo de Joint Point ......................................................................................... 11 Crosscutting dinámico .......................................................................................... 18 Aspectos ............................................................................................................ 24 Resumen ............................................................................................................ 25 Ejemplos reales ................................................................................................... 26 Bibliografía ................................................................................................................ 33 Motivaciones Antes de profundizar en la temática propia de la orientación a aspectos y sus aplicaciones en el mundo real, sería conveniente describir las motivaciones principales que han ocasionado la escritura de este capítulo de la memoria. La primera de ellas ha sido la intención de introducir al lector en algunas de las técnicas de desarrollo avanzadas utilizadas en la actualidad por los equipos de desarrollo de software más vanguardistas. La segunda está relacionada con el desarrollo de nuevas herramientas de programación y, por ende, con la herramienta desarrollada como ejemplo de este proyecto: R-Eclipse. Si el lector desconoce muchos de los términos definidos en esta sección no se preocupe, a lo largo del capítulo comprenderá la terminología aquí utilizada. En los últimos años han surgido muchos lenguajes similares a Java que se ejecutan sobre la propia máquina virtual de este último (JVM), lo cual es un indicador bastante fiable del futuro del desarrollo de aplicaciones sobre la plataforma Java. 1 Sin embargo, Eclipse y su solución JDT, no ofrecen soporte para la integración de estos nuevos lenguajes en su modelo Java subyacente. Por ejemplo, no existe un modo de incluir jerarquías de tipos,jerarquías de llamadas, etc. 1 R Eclipse no ha utilizado el enfoque descrito en esta sección por dos motivos principalmente; el primero de ellos es que R no es un lenguaje similar a Java ni corre bajo su máquina virtual. El segundo de ellos consiste en que el framework base de desarrollo, DLTK, no utiliza la arquitectura descrita en estas líneas.

description

Intro to aspect oriented programming and AspectJ

Transcript of Aspect Oriented Programming introduction

Page 1: Aspect Oriented Programming introduction

1

Chapter 1. Aspect OrientedProgramming

Table of ContentsMotivaciones ................................................................................................................ 1Evolución de las metodologías de programación ................................................................ 3AOP en el mundo real ................................................................................................... 4

Hype Cycle .......................................................................................................... 4¿Dónde se utiliza AOP? ......................................................................................... 6

Introducción a AOP ...................................................................................................... 7Metodología AOP ................................................................................................. 7Anatomía de un lenguaje orientado a aspectos ........................................................... 8Beneficios de la metodología AOP ........................................................................... 9Verdades y mentiras sobre AOP ............................................................................ 10

Visión general de AspectJ ............................................................................................. 11Introducción a AspectJ ......................................................................................... 11Modelo de Joint Point ......................................................................................... 11Crosscutting dinámico .......................................................................................... 18Aspectos ............................................................................................................ 24Resumen ............................................................................................................ 25Ejemplos reales ................................................................................................... 26

Bibliografía ................................................................................................................ 33

MotivacionesAntes de profundizar en la temática propia de la orientación a aspectos y sus aplicaciones en el mundoreal, sería conveniente describir las motivaciones principales que han ocasionado la escritura de estecapítulo de la memoria.

La primera de ellas ha sido la intención de introducir al lector en algunas de las técnicas de desarrolloavanzadas utilizadas en la actualidad por los equipos de desarrollo de software más vanguardistas.La segunda está relacionada con el desarrollo de nuevas herramientas de programación y, por ende,con la herramienta desarrollada como ejemplo de este proyecto: R-Eclipse. Si el lector desconocemuchos de los términos definidos en esta sección no se preocupe, a lo largo del capítulo comprenderála terminología aquí utilizada.

En los últimos años han surgido muchos lenguajes similares a Java que se ejecutan sobre la propiamáquina virtual de este último (JVM), lo cual es un indicador bastante fiable del futuro del desarrollode aplicaciones sobre la plataforma Java.1Sin embargo, Eclipse y su solución JDT, no ofrecen soportepara la integración de estos nuevos lenguajes en su modelo Java subyacente. Por ejemplo, no existeun modo de incluir jerarquías de tipos,jerarquías de llamadas, etc.

1R Eclipse no ha utilizado el enfoque descrito en esta sección por dos motivos principalmente; el primero de ellos es que R no es un lenguajesimilar a Java ni corre bajo su máquina virtual. El segundo de ellos consiste en que el framework base de desarrollo, DLTK, no utiliza laarquitectura descrita en estas líneas.

Page 2: Aspect Oriented Programming introduction

Aspect Oriented Programming

2

Figure 1.1. Herramientas para nuevos lenguajes

Algunos de los problemas que se encuentran los ingenieros de software cuando intentan construirherramientas para algunos de los lenguajes descritos anteriormente son:

• Necesidad de acoplarse al modelo ofrecido por JDT. No se puede.

• Necesidad de acoplarse al motor de indexación de código fuente. No se puede.

• Necesidad de acoplarse al parser de JDT. No se puede.

Una aproximación utilizada por muchos entornos de desarrollo de lenguajes actuales como pueden serScala o Groovy es la utilización del servicio de tejido de JDT. Las características principales son:

• Utiliza AspectJ añadiendo puntos de unión al modelo JDT

• Se encapsula en puntos de extensión de Eclipse, haciéndolo extensible a terceras partes.

• Utiliza un proyecto de Eclipse conocido como Equinox Aspects que soporta el proceso de tejido entiempo de carga en un entorno OSGI.

El siguiente gráfico ilustra como funciona el proceso anterior:

Page 3: Aspect Oriented Programming introduction

Aspect Oriented Programming

3

Figure 1.2. Proceso de acoplamiento al JDT

A lo largo de las siguentes secciones se introducirá la terminología AOP así como la definición desus elementos más relevantes.

Evolución de las metodologías deprogramación

La ingeniería del software ha recorrido un largo camino desde sus inicios: desde el código máquinahasta la orientación a objetos pasando por los lenguajes procedimentales. Analizando de manerasomera la evolución de las metodologías de programación observamos cómo el modelo procedimentalintrodujo la abstracción funcional y la orientación a objetos los conceptos de composición,reutilización y encapsulación. Este último paradigma ha sido, posiblemente, una de las mayorescontribuciones al mundo del software durante toda su historia y,en la actualidad, es el paradigma deprogramación utilizado en la mayor parte de los grandes desarrollos de software.

Entre todas las ventajas del paradigma de orientación a objetos, en el párrafo anterior se destacaba,no al azar, la reutilización y la encapsulación pero . . . ¿siempre es posible ubicar en el mismo lugartodas las tareas relacionadas con una misma función?, ¿en alguna ocasión has visto un fragmento decódigo que no encaja en ninguna clase en particular?.

Imaginemos un sistema en el que determinadas operaciones necesitan llevar a cabo una gestiónde transacciones. Resultaría sumamente complicado,por no decir imposible, modularizar todos losconceptos necesarios en un sistema transaccional: inicialización, comunicación con el manager detransacciones, rollbacks, . . . Esto es debido a que todos los métodos de un objeto que requierenun control de transacciones necesitan ser conscientes que la operación a realizar se ejecuta bajo uncontrol transaccional, para comportarse de manera acorde al funcionamiento requerido. Resumiendo,el código encargado de la gestión de transacciones estaría ubicado en cada uno de los objetos quelo necesite. La solución comunmente adoptada a este problema es copiar y pegar el código en todasaquellas partes en las que es necesario, resultando evidente, que dicha solución no permite disponerde una buena modularización y dificulta las labores de mantenimiento y evolución del código. Este

Page 4: Aspect Oriented Programming introduction

Aspect Oriented Programming

4

fenómeno es conocido como scattering , puesto que el código relacionado con un mismo asunto seencuentra repartido a lo largo de todo el sistema.

Sumemos, además, que los módulos que contienen código relativo a muchos asuntos diferentes tiendena ser, en general, menos reutilizables. El fenómeno en el que diferentes asuntos son entremezcladosen el código se conoce como tangling .

La problemática introducida en los párrafos anteriores, tangling y scattering , afecta al diseño ydesarrollo de software de muchas y diferentes maneras. Veamos alguna de las principales:

• Trazabilidad reducida. La implementación de diferentes conceptos en un mismo lugar dificulta elproceso de establecimiento de una relación entre los requisitos y su implementación y viceversa.Así por ejemplo, para completar la trazabilidad del requerimiento de autenticación podríamos llegara examinar todos los módulos del sistema.

• Baja producitividad. Varios conceptos no relacionados que han sido implementados en un mismolugar ocasiona que la atención se disperse a lo largo de todos ellos. La falta de un objetivoconcreto provoca que los desarrolladores se vean obligados a manejar diferentes conceptos norelacionados con el objetivo principal. En muchas ocasiones,la construcción de un módulo implicarála participación de diversos desarrolladores, con diferentes perfiles, o que el desarrollador tengaconocimiento en todos los ámbitos que se están incluyendo en el nuevo módulo.

• Escasa reutilización del código. Los conceptos implementados en un módulo podrían ser requeridospor otros módulos con funcionalidades similares

• Baja calidad. El code tangling provoca que el código sea más difícil de leer, de ubicar los potencialesproblemas y de hacer revisiones del mismo. Por ejemplo, la revisión de código de un módulo enel que se implementan diversos conceptos requerirá la presencia de expertos en cada uno de ellos.A menudo muchos de estos expertos no estarán disponibles de manera simultánea, y el resto noprestará demasiada atención en los temas que se encuentren fuera de su área de conocimiento.

• Dificultad para llevar a cabo evoluciones. La falta de recursos o una visión incompleta derivan en undiseño que maneja únicamente los conceptos actuales. Cuando aparezcan nuevos requerimientos,amenudo, nos veremos obligados a reimplementar. Dado que la implementación no se encuentramodularizada,la inclusión de un nuevo requerimiento podría obligar a realizar cambios en todoslos módulos.

Los problemas descritos en los puntos anteriores han servido como impulso en la búsqueda de nuevosy mejores enfoques en la arquitectura, diseño e implementación. AOP ofrece una solución a todos losproblemas anteriores.

AOP en el mundo real¿Qué lugar ocupa la orientación a aspectos en el mundo real? ¿Deberíamos prestarle atención oignorarlo por completo? ¿Cuáles son los beneficios aportados? ¿y los posibles riesgos de adopción deesta tecnología?. Estas y otras preguntas serán respondidas, desde un punto de vista práctico, en lossiguientes subapartados de esta sección.

Hype Cycle

Hype Cycle es una representación gráfica del grado de madurez, adopción y aplicación en el mundoreal de una tecnología determinada. Es importante comprender bien el gráfico anterior, y la posiciónde la tecnología que se está considerando; en este caso, AOP, puesto que se dispondrá de una visiónmucho más ajustada de los riesgos y beneficios a los que nos estamos exponiendo.

Page 5: Aspect Oriented Programming introduction

Aspect Oriented Programming

5

Figure 1.3. Diagrama de componentes de R-Eclipse

La interpretación de la curva Hype Cicle implica cinco fases diferentes las cuales analizaremos acontinuación, relacionándolas, evidentemente con AOP.

Activación de la tecnología

Este es el momento en el que la tecnología aparece con la intención/promesa de solucionar un conjuntodeterminado de problemas. Podría ser el anuncio de un nuevo producto o la liberación de una nuevaversión de un producto ya existente.

En el caso de AOP, este proceso de activación se produjo en 2002 con el lanzamiento de AspectJ 1.0,seguido de una liberación mucho más importante (AspectJ 1.1) en el año 2003. Mucha gente se diocuenta del potencial de AspectJ, especialmente su utilización en aplicaciones empresariales.

Expectativas irreales ("peak")

Durante esta fase la tecnlogía se hace muy popular. Todo el mundo quiere conocerla y tiene unaopinión sobre ella aunque muy poca gente la utiliza en aplicaciones reales.

Durante el año 2004 la mayoría de desarrolladores que trabajaban en Aspectj y AspectJ DevelopmentTools (AJDT) eran integrantes de IBM. Esta inversión por parte de IBM proporcionó una base sólidaa AspectJ.

La ausencia de una adopción masiva hizo que el uso de la tecnología se conviertiese en una auténticaaventura. Afortunadamente para AspectJ el pico en esta fase no fue demasiado eleveado, sobre tododebido al manejo de las expectativas que realizaron sus principales evangelistas. Esta gestión provocóun pico más bajo en el hype cycle, lo que supuso una caída mucho menor en la siguiente fase.

Desilusión

Esta es la fase de ciclo Hype en la que la tecnología comienza a perder toda la atención que se le habíaprestado hasta el momento.

Mientras que los equipos que la adoptaron desde sus inicios continuan utilizándola con el objetivode obtener una ventaja competitiva, muchos otros comienzan a observarla con cierto escepticismo.Nuevas tecnologías aparecen en escena aportando soluciones diferentes al mismo problema. Resulta

Page 6: Aspect Oriented Programming introduction

Aspect Oriented Programming

6

interesante destacar que muchos de estos nuevos competidores están en la fase de "expectativasirreales".

AOP atravesó esta fase durante 2006 aproximadamente. Enterprise Java Beans ofrecía unaseria competencia, permitiendo implementar funcionalidades transversales como seguridad otransaccionalidad de una manera modular. Pero EJB no era el único competidor, y tampoco el másimportante. La aparición de lenguajes dinámicos como Groovy o Ruby y sus frameworks asociados,Grails y Rails, supuso una dura competencia para AOP. El modelo de metaprogramación del quedisponen estas tecnologías facilitaba una nueva solución para realizar la modularización de funcionestransversales.

Viendo la luz

Numerosos factores intervienen en el desarrollo de esta fase: maduración de la tecnología, cambiosen la misma para acercarse a la realidad, búsqueda de un contexto de uso en el que realmente se causeimpacto o la "desilusión" con otras alternativas, que en su momento fueron competidores, son algunasde ellas.

En el caso de AOP, el comienzo de esta fase se produjo cuando algunos de los líderes del proyectoabandonaron IBM para fichar por SpringSource:Adrian Colyer,Andy Clement, Andrew Eisinberg, . . .,conviertiendo a AspectJ en un proyecto más del portfolio de Spring. Analicemos los factoresenumerados anteriormente:

• Acercamiento a la realidad:La introducción de anotaciones en Java 5, los cambios en la sintáxiso la supresión del proceso de weaving si se utiliza conjuntamente con Spring fueron algunos delos cambios realizados. La mejora en las herramientas de desarrollo fue otra de las respuestas a lasnecesidades reales de los usuarios.

• Contexto de utilización: la influencia de Spring: En sus inicios AspectJ carecía de un contextode utilización definido (C nació en el ámbito de los sistemas operativos, C++ en el contexto deinterfaz de usuario, etc). Ha sido Spring la que le ha proporcionado a AspectJ un contexto de usobien definido: la aplicaciones empresariales.

• Desilusión con los competidores: Anteriormente indicamos que EJB permitía modularizar losconceptos transversales de un sistema. Los desarrolladores se dieron cuenta de que la soluciónofrecida era demasiado pesada en la mayoría de las ocasiones. La versión 3 de EJB introdujointerceptores, un concepto similar a los advices de AspectJ, aunque carecían de un modelo de unión.

Los lenguajes dinámicos ofrecen una gran alternativa a AspectJ aunque son relativamente nuevos.Tendremos que esperar el paso del tiempo y el uso en grandes aplicaciones empresariales paradeterminar la evolución de los mismos, y ver cómo continúa evolucionando AspectJ.

Plena productividad

Es la última fase definida en el ciclo Hype. En esta situación la tecnología está ampliamente difundiday se utiliza en las solución de problemas para los que ofrece una gran respuesta. Será en esta fasecuando se produzca una aceptación mavisa de la tecnología.

En la actualidad,Java o C , se encuentran en esta fase. AOP y AspectJ deberán alcanzar este nivel conel paso del tiempo.

¿Dónde se utiliza AOP?A continuación se analizarán algunos de los principales ámbitos de aplicación de AOP

Aplicaciones empresariales

Gestión de transacciones, seguridad, auditoría, monitorización, gestión de la concurrencia, manejode errores y un largo ecétera son funcionalidades transversales en la mayoría de aplicacionesempresariales.

Page 7: Aspect Oriented Programming introduction

Aspect Oriented Programming

7

Aquellas aplicaciones que usen Spring como base de su arquitectura ya estarán utilizando algunosde los aspectos que vienen facilitados por el framework. Gracias a las anotaciones, concretamente@Aspect, la construcción de aspectos se ha convertido en una tarea habitual.

Web y servidores de aplicaciones

Aplicación de políticas, FFDC, recolección de contextos,trazabilidad o monitorización son algunas delas funcionalidades basadas en AOP que podemos encontrar en los servidores de aplicaciones. SpringSource DM Server y TC Server son un claro ejemplo de estas funcionalidades.

Frameworks

Gestión de transacciones y seguridad son habitualmente implementadas mediante aspectos. Asimismo,otras utilizaciones de los aspectos podría ser la inyección de dependencias en objetos de dominio.Para obtener un amplio abanico de posibilidades de uso de los aspectos, el lector podría visitar losproyectos de Spring Roo o Apache Magma.

Herramientas de monitorización

El uso de aspectos facilita también la construcción de herramientas de monitorización. Muchasherramientas utilizan AspectJ como tecnología subyacente: Glassbox,Perf4J,Contract4J,JXInsight oMaintainJ son algunos de los ejemplos.

Compiladores e integración de IDE's

El mismo equipo de AspectJ utiliza la propia tecnología para extender el compilador de JDT de maneraque sea capaz de sopotar las nuevas construcciones. AJDT utilizan un proceso de weaving a través deuna implementación basada en OSGI ofrecida por el proyecto Equinox. Scala IDE en Eclipse utilizaun enfoque similar para la construcción del entorno de desarrollo.2

Introducción a AOPAOP se construye sobre metodologías existentes como OOP o programación funcional,mejorándolas con las construcciones necesarias que permiten modularizar correctamente los conceptostransversales. Por ejemplo, si se trabaja con OOP, el núcleo de nuestro sistema será implementadomediante la utilización de clases. Los aspectos serán los encargados de representar las funcionalidadestransversales y determinar cómo todos los diferentes módulos deberán ser tejidos para construir elsistema final.

Metodología AOPDesarrollar un sistema utilizando AOP es similar a un desarrollo basado en otras metodologías:determinar los requerimientos, implementarlos y construir el sistema final mediante la combinaciónde los mismos. La comunidad AOP define tres pasos:

1. Descomposición en aspectos En este paso se indentificarán los diferentes concerns , tanto lostransversales como los que componen el núcleo. Por ejemplo, en una capa de negocio encargada decalcular el IVA total de los productos los aspectos pertenecientes al núcleo sería el cálculo del IVAen sí, mientras que elementos como la transaccionalidad, registro de actividad,seguridad en hilos,manejo de cachés, . . . serían conceptos de un espectro mucho más amplio, que serán necesitadosen otros muchos módulos del sistema, y por tanto, se categorizan como conceptos transversales

2. Implementación de "concerns" En este punto tendrá que realizarse la implementación de losdiferentes requerimientos de manera independiente . Siguiendo con el ejemplo anterior, un grupo

2Ver la sección inicial de este capítulo

Page 8: Aspect Oriented Programming introduction

Aspect Oriented Programming

8

sería el encargado de realizar la implementación del módulo de lógica de negocio encargado decalcular el IVA, otro grupo llevaría a cabo la gestión del logging, un tercer grupo sería el encargadode asegurarse que las operaciones fuesen thread safe , y así sucesivamente.

3. Recomposición de aspectos . En este paso se deben definir las reglas de composición mediante lacreación de módulos o aspectos . Este proceso, conocido como weaving , utiliza esta informaciónpara construir el sistema final.

La principal aportación de AOP es la independencia de los "concerns" en el momento de suimplementación. El modo en que se realiza la implementación permite una completa trazabilidad entrelos requerimientos y su implementación, por lo que el sistema final será más fácil de comprender,implementar o adaptar ante futuros cambios

Anatomía de un lenguaje orientado a aspectos

La orientación a aspectos es simplemente una metodología por lo que será necesario definir el lenguajey ofrecer un conjunto de herramientas para trabajar con la misma. Al igual que otra metodología deprogramación, una implementación concreta de AOP constará de dos partes:

• Especificación del lenguaje encargado de describir las construcciones y sintaxis que serán utilizadasen la construcción y el tejido de todos los "concerns", tanto los pertenecientes al núcleo como lostransversales.

• La implementación del lenguaje es la encargada de verificar la adherencia del código a laespecificación del lenguaje y de trasladar el código a un ejecutable capaz de ser comprendido poruna máquina. Esta tarea,habitualmente,es realizada por un compilador o un intérprete.

Especificación del lenguaje AOP

Cualquier implementación de la metodología AOP requiere la definición de dos lenguajes: el primerode ellos permitirá realizar la implementación de los requisitos individuales mientras que gracias alsegundo podremos definir las reglas que "tejen" el conjunto de módulos independientes.

• Implementación de concerns .Al igual que en otras metodologías, los requisitos se implementanen módulos que contienen los datos y el comportamiento necesario para ofrecer sus servicios.Imaginemos por ejemplo que estamos construyendo el núcleo del concern de seguridad; dichonúcleo mantendrá un manager de control de accesos y una colección de elementos ( voters ).Habitualmente,tanto los concerns transversales como los del núcleo se implementan mediante lautilización de lenguajes estándar como pueden ser C++ o Java.

• Especificación de reglas de "tejido". Las reglas de tejido especifican cómo debemos integrar losdiferentes concerns que hemos implementado para componer el sistema final. El lenguaje utilizadopara definir estas reglas puede ser una evolución del lenguaje natural o algo completamentediferente. Así por ejemplo, podríamos ofrecer una implementación de la metodología AOP en la queJava es el lenguaje base y la definición de reglas de tejido se realiza mediante un DSL implementadoen Groovy .

Implementación de AOP

La implementación del lenguaje debe llevar a cabo dos acciones:combinar los aspectos individualesmediante las reglas de tejido,para, posteriormente, convertir la información resultante en códigoejecutable. El primero de los dos pasos anteriores es conocido como weaving, y el procesadorencargado de realizar dicha tarea es el weaver.

• Proceso de weaving . Tal y como argumentaba la introducción de este punto, el proceso de weavinges el encargado de componer el sistema final mediante la composición de los diferentes concernssiguiendo las pautas establecidas en las reglas de tejido . Estas reglas son definidas en aspectos

Page 9: Aspect Oriented Programming introduction

Aspect Oriented Programming

9

independientes del núcleo del sistema por lo que con unas nuevas reglas de "tejido" podríamosconstruir un sistema final completamente diferente.

• Procesador (Weaver) El procesador encargado de llevar a cabo el proceso de weaving descrito enel punto anterior es comunmente conocido como weaver

Una posible implementación sería utilizar una transformación código a código (un compilador). Deese modo, el compilador de aop "tejería" los aspectos junto al resto de clases generando un nuevocódigo ya "tejido". Una vez finalizado este proceso, el código generado anteriormente serviría comoentrada para el compilador de lenguaje base el cual sería el encargado de generar el ejecutable.Utilizando el enfoque anterior, una aproximación basada en C++ convertiría todos los archivosindividuales (aspectos y clases) en código C++ tejido(weaving).

El siguiente diagrama ilustra la aproximación descrita en el párrafo anterior:

Figure 1.4. Proceso de generación del sistema final

Beneficios de la metodología AOPLa mayoría de las críticas sobre AOP destacan que en muchas ocasiones es demasiado complejo.Evidentemente, es necesario un poco de tiempo y paciencia para conseguir ser un experto. Sinembargo, el motivo principal de su complejidad es que se trata de una tecnología relativamente nueva.

Algunos de los beneficios más detacables de esta metodología son:

• Responsabilidades claramente diferenciadas . Cada módulo es el responsable de su funcionalidadprincipal; dejando de lado los conceptos transversales. Así por ejemplo, un módulo cuyo principalcometido es implementar la lógica de acceso a datos de un sistema de ventas por internet, no tendráque preocuparse de realizar pooling sobre la base de datos o de la transaccionalidad. Gracias a estaclara asignación de responsabilidades se consigue una alta trazabilidad entre los requisitos y sucorrespondiente implementación.

• Incremento de la modularidad . Utilizando AOP se consigue manejar cada uno de los conceptosde manera independiente con un acoplamiento mínimo. Incluso aunque estén presentes conceptostransversales que afecten al sistema completo, la implementación es modular.

• Retraso en las decisiones de diseño .Cuando se arquitecta un nuevo sistema siempre aparece elsiguiente dilema: ¿se debe realizar un diseño sumamente complejo y detallado que intente abarcartodas las funcionalidades,incluso las futuras? o, por el contrario, ¿debe arquitectarse una soluciónque se corresponda con la situación actual?.

Gracias a AOP, el arquitecto de la solución, puede retrasar la toma de determinadas decisiones dediseño dado que los futuros requerimientos se implementarán en aspectos independientes. Dando unpaso más adelante, AOP conforma un gran equipo junto con una metodología ágil como puede ser

Page 10: Aspect Oriented Programming introduction

Aspect Oriented Programming

10

XP (siglas en inglés de Programación Extrema) siguiendo la práctica del principio YAGNI (siglasen inglés de No lo vas a necesitar ) . De este modo, podemos seguir el principio anterior, dandovida únicamente a las funcionalidades requeridas e implementando futuros requerimientos sin lanecesidad de grandes modificaciones en el sistema.

• Sencillez en las mejoras . AOP permite añadir una nueva funcionalidad sin más que desarrollar unnuevo aspecto (el cual no afecta al núcleo del sistema). Gracias a ello, el tiempo de respuesta antenuevos requerimientos disminuye notablemente.

• Incremento en la reutilización del código .Puesto que AOP implementa cada aspecto en un móduloindependiente, cada uno de ellos es independiente del resto. En general, cada uno de ellos no suelentener conocimiento del resto de elementos que conforman el sistema final. Realmente, el únicoelemento consciente del acoplamiento entre los diferentes módulos son las reglas de tejido , demanera que, si cambiamos éstas, podemos componer un sistema final completamente diferente.

• Reducción de costes y accesos al mercado más rápidos .Las características descritas en lospuntos anteriores generan sistemas más rápidos, tanto en su desarrollo como en su implantación. Eliminando la necesidad de modificar múltiples módulos para la implementación de unnuevo concepto transversal, AOP provoca que dicha implementación sea más barata. Asimismo,permitiendo que los desarrolladores estén centrados en su especialidad logramos que el coste deldesarrollo disminuya.

Verdades y mentiras sobre AOP

En los últimos años AOP ha sufrido un gran crecimiento aunque,en algunas ocasiones, todavía sepercibe demasiado complicado, tanto en su implementación como en su proceso de aprendizaje. Acontinuación veremos algunas hipótesis y los motivos por los que las mismas son consideradas ciertaso falsas:

• AOP no soluciona nuevos problemas . Esta afirmación es completamente cierta. La orientación aaspectos no ofrece solución a problemas irresolubles sino que aporta soluciones más sencillas yelegantes a los problemas actuales. Al fin y al cabo, no hay nada que no podamos implementar concódigo máquina.

• Flujos complicados de seguir . De nuevo esta afirmación es cierta. En muchas ocasiones, enfunción de la complejidad del sistema que estemos construyendo, el orden en el que se ejecutan lasinstrucciones puede resultar complicado de seguir.

La afirmación anterior también es cierta para otras metodologías ajenas a AOP. En OOP, el usodel polimorfismo hace que analizar el flujo de ejecución de un programa no sea una tarea sencilla.Incluso en lenguajes procedimientales, como podría ser C, el uso de punteros a funciones dificultalas tareas de seguimiento del programa.

• AOP promueve malos diseños . En esta ocasión la afirmación es falsa. Una aproximación orientadaa aspectos no es la solución para un mal diseño sino que simplemente facilita nuevos modos deresolución de problemas en aquellas áreas en las que lenguajes procedimientales u orientados aobjetos presentan carencias.

• Los interfaces de las metodologías OOP son suficientes . De nuevo en esta ocasión, laafirmación anterior es falsa. La técnica descrita propone utilizar un interfaz e ir intercambiando lasimplementaciones subyancentes (nótese que esto no implica cambios en el API). Puede parecer asimple vista que esta solución es satisfactoria, pero dista mucho de ser así, puesto que necesitamosinvocar al código en todos aquellos lugares en los que corresponda. Esta técnica sirve de granayuda (tanto en OOP como AOP), pero en ningún momento los interfaces son una alternativa a laorientación a aspectos.

• AOP supone una ruptura de la encapsulación . Esto afirmación es cierta aunque con ciertos maticespuesto que dicha ruptura se realiza de una manera controlada y sistemática. Las clases en OOP

Page 11: Aspect Oriented Programming introduction

Aspect Oriented Programming

11

encapsulan todo el comportamiento, mientras que AOP elimina estos niveles de control de lasmismas.

• AOP reemplazará a OOP . Falso. Los conceptos principales seguirán siendo implementados enOOP ( o puede que en un lenguaje procedimantal como puede ser C). AOP añade un nuevo conjuntode conceptos adicionales a la metodología orientada a objetos. Efectivamente, AOP cambiaráel modo en el que se utilizan las metodologías actuales para la implementación de conceptostransversales.

Visión general de AspectJAspectJ es una extensión orientada a aspectos de propósito general al lenguaje Java. Puesto que esuna extensión del lenguaje Java, cualquier programa escrito en dicho lenguaje es un programa AspectJválido. Un compilador AspectJ genera archivos .class de acuerdo a la especificación del bytecodede Java de manera que cualquier implementación de la máquina virtual sea capaz de ejecutar dichosarchivos.

El lenguaje AspectJ , de acuerdo a los conceptos descritos en el apartado anterior, consta de dospartes: la especificación del lenguaje que define los conceptos principales implementados medianteclases Java, y las extensiones AOP que permiten realizar el tejido de los conceptos transversales. Laimplementación del lenguaje facilita herramientas como compiladores, depuradores e integración conla mayoría de IDE´s modernos.

Los siguientes apartados servirán de introducción a AspectJ y algunos conceptos avanzados gracias alos cuales se podrá comenzar a escribir programas simples.

Introducción a AspectJ

El compilador de AspectJ es el encargado de utilizar los módulos que contienen las definiciones de lasreglas de tejido para añadir nuevo comportamiento a los módulos que implementan las funcionalidadesprincipales. El proceso anterior no realiza ninguna modificación sobre el código fuente del núcleodado que el proceso de tejido se realiza sobre el bytecode generado por el compilador.

Modelo de Joint Point

El modelo de joint point (no vamos a traducir el término) está compuesto de dos partes claramentediferenciadas: los "join point", que no son más que puntos en la ejecución de un programa, y los"pointcuts", un mecanismo de selección de los puntos anteriores.

Imaginemos por un momento que nos encontramos desarrollando un sistema que necesita gestión dela seguridad, algo muy común en el mundo en el que nos movemos, y, que, debido a la naturalezatransversal del mismo, elegimos AOP como enfoque principal de nuestra solución. ¿Cuáles son lospasos que deberíamos seguir?

1. Identificar los puntos del sistema que necesitan ser protegidos, comprobando, antes de realizar elacceso, que el usuario está autenticado y tiene los privilegios necesarios para hacerlo.

En resumen, estamos identificando los "joint point" que requieren ser securizados.

2. Construiremos un pointcut (o varios, todos los que sean necesarios), que permita la selección delos "joint point" descritos en el punto anterior.

3. Construiremos un aspecto que encapsule toda la lógica de seguridad requerida.

Los conceptos anteriores son sumamente importantes dado que componen la base de AOP. Lossiguientes subapartados profundizarán en cada uno de ellos.

Page 12: Aspect Oriented Programming introduction

Aspect Oriented Programming

12

Joint Point

Como ya se definió anteriormente, un join point es un punto de ejecución en un sistema. Así porejemplo, el acceso al campo de una clase, la ejecución de una función o una sentencia for son ejemplosde join points.

AspectJ solamente expone un subconjunto de todos los posibles joint points, limitando de este modo,el acceso a las construcciones más estables.

Pointcuts

Es un artefacto que nos permite seleccionar joint points y recuperar su contexto.Veamos algunas delas características principales:

Selección de joint points

Los pointcut especifican un criterio de selección. Utilizaremos tipos, campos, métodos, anotaciones,etc para generar dichas definiciones. También podremos establecer condiciones en tiempo deejecución que tendrán que cumplirse en el joint point seleccionado.

Determinación del contexto

Los joint point disponen de información en tiempo de ejecución. Determinados pointcuts puedenrecolectar dicha información y pasársela al advice. Por ejemplo, la llamada a un método de un objetotendrá disponible el propio objeto que realiza la llamada y los argumentos que se están pasando.

Utilización de signaturas

En Java, todos los elementos que componente un programa tienen una signatura. La utilización depatrones para dichas signaturas permiten a los pointcuts especificar las reglas que permiten seleccionarlos joint point deseados.

Categorías de joint points

A continuación se verá un conjunto de categorías de joints points expuestas por AspectJ. A pesar deser un número considerable de categorías, no se han incluido todas, sino aquellas que se utilizan conmayor frecuencia. Si el lector desea realizar una lectura más profunda aquí podrá encontrar todo loque necesita: AspectJ Programming Guide [http://www.eclipse.org/aspectj/docs.php]

Table 1.1. Categorías de joint points expuestas por AspectJ (resumen)

Categoría Joint Point Expuesto Código que representa

Método Execution Cuerpo del método

Método Call Invocación del método

Constructor Execution Ejecución de la lógica de creación de un objeto

Constructor Call Invocación de la lógica de creación de un objeto

Acceso a un campo Read Lectura de un objeto o el campo de una clase

Acceso a un campo Write Escritura de un objeto o el campo de una clase

Proceso de excepciones Handler Bloque catch para manejar una excepción

Inicialización Class init Proceso de carga de una clase (class loading)

Inicialización Object init Inicialización de un objeto en un constructor

Inicialización Object pre-init Pre-inicialización de un objeto en un constructor

Advice Execution Ejecución de un advice

Page 13: Aspect Oriented Programming introduction

Aspect Oriented Programming

13

Conceptos básicos

A continuación se analizarán los elementos básicos que se deben conocer para definir un pointcut.

Pointcuts anónimos o con nombre

Se permite la declaración de pointcuts de cualquiera de los dos tipos. Los primeros son similares alas clases anónimas, y por tanto se definen en el lugar en el que se van a utilizar. En el caso de lossegundos, podremos referenciarlos desde múltiples lugares, permitiendo de este modo su reutilización.

Operadores

AspectJ proporciona el operador unario de negación (!) y dos operadores binarios: && y ||, graciasa los cuales se permite construir reglas de matching complejas mediante la combinación de pointcutsmás sencillos.

Tanto la semántica como la precedencia es la misma que en el lenguaje Java. Así por ejemplo,enel caso del operador binario &&, se seleccionarán aquellos joint points que concuerden con los dospointcuts que actúan como operandos.

Signaturas: sintaxis y ejemplos

Las signaturas son la base de la definición de los pointcuts. El lenguaje debe facilitar una manerasencilla que permita definir criterios de selección sobre los diferentes aspectos transversales queestamos implementando. En el caso de AspectJ, se utilizan expresiones regulares (wildcards) encombinación a las signaturas. Los siguientes wildcards son soportados:

• * especifica cualquier número de caracteres, exceptuando el punto (.). En la signatura de un tipo,denota una parte de un tipo o de un paquete. En otros patrones denota una parte del nombre (porejemplo en métodos o campos)

• .. determina cualquier número de caractéres, incluyendo en este caso cualquier número de puntos(.). En la signatura de un tipo representa cualquier paquete o subpaquete. En la signatura de unmétodo representa cualquier número de argumentos.

• + denota cualquier subtipo de un tipo determinado.

A lo largo de los siguientes subapartados veremos, a través de una serie de ejemplos, los diferentespatrones de signaturas ofrecidos por AspectJ que podemos utilizar para seleccionar dierentes jointpoints

Signaturas de tipos

Table 1.2. Ejemplos de signaturas de tipos

Patrón de lasignatura

Descripción Ejemplos de tipos concordantes

AstVisitor El tipo AstVisitor Sólo el tipo AstVisitor concuerda (nitipos base ni derivados)

*AstVisitor Cualquier tipo cuyo nombre termine enAstVisitor

Por ejemplo, HighlightingAstVisitor oSemanticAstVisitor concuerdan con elpatrón

java.*.Date El tipo Date en cualquier subpaquetedirecto del paquete java

java.util.Date o java.sql.Date sonejemplos de tipos concordantes

javax..* Cualquier tipo en el paquete javax y ensus subpaquetes (tanto directos comoindirectos)

Cualquier tipo en el paquetejavax.security así como cualquierade sus subpaquetes indirectos comojavax.security.auth.login

Page 14: Aspect Oriented Programming introduction

Aspect Oriented Programming

14

Patrón de lasignatura

Descripción Ejemplos de tipos concordantes

javax..*Model Todos los tipos en el paquete javax(subpaquetes directos e indirectos)cuyo nombre termine en Model, y todoslos subtipos de estos.

TableModel, TreeModel y sussubtipos como DefaultTreeModel oDefaultTableModel.

Singaturas de tipos: anotaciones

Table 1.3. Ejemplos de signaturas de tipos: anotaciones

Patrón de lasignatura

Descripción Ejemplos de tipos concorndantes

@Secured User El tipo User anotado con la anotaciónSecured

@Secured class User{. . .}

@Entity * Cualquier tipo anotado con la anotaciónEntity

@Entity class Section {. . .},@Entityclass Report {. . .}

@Transactional*Manager+

El tipo Manager y cualquiera de susclases derivadas que estén anotados conuna anotación cuyo nombre comienzepor Transactional

@TransactionalDefault classManager{},@TransactionalOracleclass OracleManager extendsManager{}

Signaturas de tipos: generics

Table 1.4. Ejemplos de signaturas de tipos: generics

Patrón de lasignatura

Descripción Ejemplos de tipos concordantes

Map<Integer,String>

El tipo Map cuyo primer argumentogenérico está fijado a Integer y elsegundo a String

En este caso únicamente concordará eltipo Map<Integer,String>

*<User> Cualquier tipo genérico cuyo únicoargumento genérico sea de tipo User

Collection<User>,List<User>, . . .

Collection<?extends User>

El tipo Collection con un parámetro detipo User o derivado

Collection<User>,Collection<DomainUser>, . . .

Collection<?super User>

El tipo Collection, cuyo parámetro seráuno de los tipos base de User

Collection<Serializable>,Collection<BaseUser>, asumiendoque, User extiende o implementa,directa o indirectamente, Serializable yBaseUser

Combinando pointcuts: operadores

Table 1.5. Signaturas de tipo: operadores

Patrón de lasignatura

Descripción Ejemplos de tipos concordantes

!Collection Cualquier tipo excepto Collection User,Model, List (aunque sea subclasede Collection)

Set || Map Los tipos Set o Map Los tipos Set y Map únicamente

!@Transactional Cualquier tipo que se encuentre anotadopor por la anotación Transactional

class NonTransactionalManager{}

@Serializable@Encrypted *

Cualquier tipo que se encuentre anotadopor las dos anotaciones

@Serializable @Encrypted classUserCredentials{}

Page 15: Aspect Oriented Programming introduction

Aspect Oriented Programming

15

Patrón de lasignatura

Descripción Ejemplos de tipos concordantes

(@Serializable ||@Encrypted) *

Cualquier tipo que esté anotado poralguna de las dos anotaciones

@Serializable class User {}

Signaturas de métodos y constructores

Table 1.6. Signaturas de métodos

Patrón de lasignatura

Descripción Ejemplos de métodos concordantes

public voidUser.set*(*)

Cualquier método público de la claseUser cuyo nombre comienze por set,cuyo tipo de retorno sea void, y queespere un único argumento

class User{ public void setName(Stringname){} }

public voidUser.*()

Cualquier método público de la claseUser cuyo tipo de retorno sea void y queno espere argumentos

class User { public void updateInfo(){}}

public * User.*() Cualquier método público de la claseUser que no espera argumentos yretorna cualquier tipo

class User{ public UserInfogetUserInfo(){}}

public * User.*(..) Cualquier método público de la claseUser que retorna cualquier tipo, yespera cualquier número y tipo deargumentos (incluido cero)

class User{ public UserInfogetUserInfo(){},public DateupdatesBetween(Date first,Date last){}}

* *.*(..) o * * (..) Cualquier método independiente de sutipo, del tipo de retorno, de su nombrey de los argumentos que espere

Cualquier método del sistema

!public * User.*(..) Cualquier método que no sea público(privado,protegido o paquete)

class User {protected getUserInfo(){}}

* * (..) throwsRecognitionException

Cualquier método que declare quepuede lanzar una excepción de tipoRecognitionException

clas AntlRBasedParser { publicvoid parser(String file) throwsRecognitionException}

* User+.*(..) Cualquier método en la clase User y sussubclases

class UserDetails extends User {}

UserUserService.*(..)

Cualquier método del tipo UserServicecuyo tipo de retorno sea User. Si algunade las subclases sobreescribe el tipode retorno con un subtipo de User(mediante el tipo de retorno covarianteintroducido en Java 5) también seráseleccionado.

class UserService{public UserretrieveUser(String name){}} classDetailUserService extendsUserService{public DetailedUserretrieveUser(String name){}}

La signatura en el caso de los constructores difiere de la signatura de métodos en los siguientesaspectos:

• Los constructores no tienen tipo de retorno por lo que no se permite utilizar el valor de retorno enla especificación de un pointcut de este tipo.

• Dado que los nombres de los constructores no pueden ser libres (tienen que utilizar el mismo nombrede la clase), la parte de la signatura destinada al nombre será sustituida con la palabra new.

• Por último, puesto que los constructores no pueden ser estáticos, no se podrá utilizar la palabrareservada static

Page 16: Aspect Oriented Programming introduction

Aspect Oriented Programming

16

Signaturas de campos

Table 1.7. Signaturas de campos de clase

Patrón de lasignatura

Descripción Ejemplos de campos concordantes

private StringUser.username

Campo privado (tanto campo de unainstancia como estático) de la claseUser

class User { private String username;}

* User.* Cualquier campo de la clase Userindependiente de sus cualificadores,tipo y nombre.

class User{private Stringusername;protected int credits;privateUserDetails details;}

* User+.* Cualquier campo de laclase User y todas sussubclases, independientemente de suscualificadores, tipo y nombre.

El ejemplo de la fila anterior o classSpecificUser extends User {privateString address;}

Implementación de pointcuts

AspectJ ofrece dos mecanimos diferentes que permiten a los pointcuts realizar la selección de los jointpoints

• Kinded pointcuts. En este caso, los pointcuts seleccionan categorías de joint points (de ahí sunombre). Así, por ejemplo, se ofrece la posibilidad de realizar matching sobre la ejecución de unmétodo

• Non-kinded pointcuts. Se seleccionan los joint point en base a la información de la que disponen,como los tipos en tiempo de ejecución o su contexto. En esta situación se seleccionan joint pointsde cualquier clase, siempre y cuando sastisfagan la condición descrita

De nuevo, al igual que en el apartado anterior, veremos las diferentes opciones disponibles, tanto paralos kinded como para los non-kinded pointcuts.

Kinded pointcuts

Table 1.8. Joint Points expuestos y tipos de pointcuts

Categoría de Joint Point Sintaxis del pointcut

Ejecución de un método execution(MethodSignature)

Llamada a un método call(MethodSignature)

Ejecución de un constructor execution(ConstructorSignature)

Llamada a un constructor call(ConstructorSignature)

Inicalización de una clase staticinitializaction(TypeSignature)

Acceso de lectura a un campo get(FieldSignature)

Acceso de escritura a un campo set(FieldSignature)

Ejecución de un manejador de excepciones handler(TypeSignature)

Inicialización de un objeto initialization(ConstructorSignature)

Pre-inicialización de un objeto preinitialization(ConstructorSignature)

Ejecución de un advice adviceexecution()

Por ejemplo, si deseamos seleccionar todas las llamadas a los métodos públicos commit() de la claseTransactionManager, escribiríamos un pointcut similar al siguiente:

call(public void TransactionManager.commit(. .))

Page 17: Aspect Oriented Programming introduction

Aspect Oriented Programming

17

Non-kinded pointcuts

Este tipo de pointctus permiten la selección de joint points basados en criterios adicionales a lassignaturas vistas anteriormente. Por ejemplo, podremos seleccionar todos los joint point donde elobjeto this es de un determinado tipo. Dicho joint point incluiría las llamadas a métodos, ejecuciones,manejadores de excepciones, etc.

De nuevo, a través de ejemplos, veremos los diferentes tipos de non-kinded pointcuts ofrecios porAspectJ

Non-kinded pointcuts basados en control de flujo

Table 1.9. Non-kinded pointcuts basados en control de flujo

Pointcut Descripción

cflow(execution(*TransactionManager.commit()))

Selecciona todos los joint points en el flujo de la ejecución decualquier operación commit de la clase TransactionManager,incluyendo la ejecución del propio método.

cflowbellow(execution(*TransactionManager.commit()))

Selecciona todos los joint points en el flujo de la ejecución decualquier operación commit de la clase TransactionManager,excluyendo la ejecución del método.

cflow(execution(@Secured * *(..)))

Todos los joint points en el flujo de la ejecución de cualquiermétodo anotado con la anotación Secured

cflow(transacted()) Cualquier joint point en el flujo de ejecución de los joint pointsseleccionados por el pointcut transacted()

Non-kinded pointcuts basados en la estructura léxica

Dentro de este tipo de pointcuts tenemos dos categorías:

• within(TypeSingnature): selecciona cualquier joint point que aparece en el cuerpo de las clases yaspectos que concuerden con el tipo especificado.

• withincode(ConstructorSignature),withincode(MethodSignature): selecciona cualquier joint pointque aparezca dentre de un método o un constructor, incluendo la definición de cualquier clase localque puediera aparecer en los mismos.

Table 1.10. Non-kinded pointcuts basados en la estructura léxica

Pointcut Descripción

within(User) Selecciona todos los joint points que aparecen dentro de la claseUser

within(User+) Selecciona todos los joint points que aparecen dentro de la claseuser y cualquiera de sus clases derivadas

within(@Transactional *) Selecciona todos los joint points que aparecen dentro de cualquierclase que se encuentre marcada con la notación Transactional

withincode(*TransactionManager.retrieve*(..))

Selecciona todos los joint points que parecen dentro de cualquiermétodo de la clase TransactionManager cuyo nombre comiencepor retrieve

Non-kinded pointcuts de ejecución

Este tipo de pointcuts nos permiten seleccionar joint points en base al tipo de los objetos en tiempode ejecución. De este modo, disponemos de:

• this(). Acepta dos formas diferentes: this(ObjectIdentifier) o this(Type). Seleccionará aquellos jointpoints cuyo objeto this sea del tipo (o el objeto) indicado.

Page 18: Aspect Oriented Programming introduction

Aspect Oriented Programming

18

• target(). Similar al concepto anterior, aunque en este caso, se utilizar el target del joint point enlugar del this

Table 1.11. Pointctucts basados en la ejecución

Pointcut Descripción

this(User) Selecciona cualquier joint point en que se la expressión this instanceof User seacierta. Así por ejemplo, seleccionará las llamadas a métodos o accesos a camposdonde el objeto actual sea de tipo User o cualquier de sus subclases.

target(User) Selecciona cualquier joint point en el que el objeto sobre el que se realiza lallamada al método es instanceof User

Non-kinded pointcuts sobre argumentos

Este tipo de pointcuts nos permiten seleccionar joint points en base al tipo de los argumentos en tiempode ejecución. Veamos los distintos tipos de argumentos, en función del tipo del joint point :

• En el caso de los joint points manejadores de excepciones el argumento será la excepción manejada.

• En los métodos y constructores, los argumentos serán los argumentos del método y constructor

• Los accesos de modificación de un campo, el argumento será el nuevo valor que va a tomar dichocampo.

Table 1.12. Ejemplos de pointctucts basados en argumentos

Pointcut Descripción

args(User, . . ,String)

Selecciona cualquier joint point de tipo método o constructor en el que el primerargumento es de tipo User (o cualquiera de sus subclases), y el último argumentoes de tipo String.

args(SqlException) Selecciona cualquier joint point con un único argumento de tipo SqlException.Seleccionaría cualquier método o constructor que esperase un único argumentode tipo SqlException, un acceso de escritura a una campo estableciendo un nuevovalor de tipo SqlException, y también seleccinaría un manejador de excepcionesde tipo SqlException

Non-kinded pointcuts condicionales

Este tipo de pointcuts nos permiten seleccionar joint points basados en una expresión condicional

Table 1.13. Ejemplos de pointcuts condicionales

Pointcut Descripción

if(debug) Selecciona cualquier joint point donde el campo estático debug (en la definicióndel aspecto) toma el valor cierto

Crosscutting3 dinámicoA lo largo de las secciones anteriores hemos analizado el modelo de joint point de AspectJ y la manerade defininir las reglas que nos permitan seleccionar aquellos joint points que sean de nuestro interés.Durante este capítulo analizaremos el modo en el que podemos alterar el comportamiento de nuestrosistema en los joint points que hayamos seleccionado mediante la definición de nuestros pointcuts.

Descripción general

Las reglas de tejido están compuestas de dos partes:

3El término crosscuting representa la naturaleza transversal de las funcionalidades que estamos añadiendo. Se ha optado por no realizar latraducción del término y utilizar la terminología orginal

Page 19: Aspect Oriented Programming introduction

Aspect Oriented Programming

19

• advice: qué deseamos hacer

• pointcuts: donde aplicamos el advice anterior

AspectJ soporta el crosscutting dinámico mediante los advices, construcciones similares a los métodosque nos permiten definir las acciones que a ejecutar en los joint points seleccionados por un pointcut.

Categorías de advices

Dependiendo de las funcionalidades que estemos implementando necesitaremos ejecutar nuestralógica en un determinado lugar del flujo de ejcución orginal; así por ejemplo, si estamos construyendola seguridad de un sistema, nuestro código tendrá que verificar dicha seguridad antes de la ejecución deljoint point. Si estuvieramos construyendo un sistema de cachés, nuestra nueva funcionalidad tendríaque ejecutarse alrededor de joint point original, intentando recuperar el valor de la caché, y en caso deque no exista, ejecutar el código real y añadirlo a la misma para futuras invocaciones. AspectJ ofrecetres categorias de advices que satisfacen los escenarios anteriores (y alguno más):

• Before Advice se ejecutan anteriormente a la ejecución del joint point

• After Advice: se ejecutan posteriormente a la ejecución del joint point. Existen tres variantesdiferentes

• After finally se ejecuta tras la ejecución del join point independientemente del resultado de dichaejecución

• After returning se ejecuta tras la ejecución del joint point siempre y cuándo ésta última hayafinalizado correctamente, es decir, sin lanzar ninguna excepción.

• After throwing se ejecuta tras la ejecución fallida de un joint point, es decir, después de que dichojoint point dispare una excepción.

• Around Advice rodean la ejecución del joint point.

Sintaxis de los advices

Aunque la sintaxis varía ligeramente dependiendo del tipo de advice que estemos escribiendo,podríamos dividir su estructura general en tres partes claramente diferenciadas:

• Declaración del advice. En esta parte de la declaración se especifica el momento de ejecución deladvice, es decir, si se ejecutará antes, después y alrededor de los joint points

• Definición de los pointcuts. Se especifican los pointcuts sobre los que se desea actuar.

• Cuerpo del advice. Definición del código a ejecutar una vez se haya alcanzado el joint pointindicado.

Veamos un ejemplo sencillo de definición de un advice:

En primer lugar defininamos un sencillo pointcut

pointcut secureOperation(User user): call( * User.*(..)) && target(user)

En el pointcut anterior estamos capturando todas las llamadas a cualquier método de la clase User, y,adicionalmente estamos recogiendo el objeto que actua como target de la llamada.

A continuación veremos un around advice para ilustrar la sintaxis:

Object around(User user):secureOperation(user){ System.out.println("Securing operation on user " + user.toString());

Page 20: Aspect Oriented Programming introduction

Aspect Oriented Programming

20

Object retValue = proceed(user); System.out.println("Finished secured operation on user " + user.toString()); return retValue;}

En la definición anterior podemos ver la estructura de la declaración de un advice descritaanteriormente

1. La parte que precede a los dos puntos indica el momento de ejecución del advice(after,before,around). En este caso, se ejecutará alrededor del joint point seleccionado.

2. La parte que sigue a los dos puntos representa el pointcut, es decir, la definición de los criteriosque determinan cuando se ejecutará el advice

3. La última parte representa el cuerpo del advice, es decir, el código que se ejecutará cuando algunode los joint point definidos por el pointcut sea alcanzado.

Advices y métodos

Al igual que los métodos de una clase, los advices se utilizan para definir comportamiento. La sintaxisde éstos últimos es similar a la de los métodos aunque existen algunas diferencias dado que los advicesson aplicados de manera automática, sin la necesidad de realizar explicitamente la invocación delmismo.

Similitudes

Analizemos las similitudes de ambos en tres categorías diferentes: declaración, cuerpo ycomportamiento.

La declaración de un advice es similar a la signatura de un método tradicional:

• Opcionalmente puede asigarse un nombre al advice mediante el uso de la anotación @AdviceName

• Recibe argumentos a través del contexto del joint point, que posteriormente podrán ser utilizadosen el cuerpo para implementar la lógica necesaria.

• Puede declarar el lanzamiento de una excepción.

En cuerpo de los advices también es muy parecido al de los métodos:

• El código del cuerpo del advice sigue las mismas reglas de acceso a miembros de otros tipos y/o aspectos.

• Se puede referenciar a la propia instancia del aspecto mediante el uso de this,

• Los advices de tipo around pueden retornar un valor.

• Los advices deben declarar las excepciones que sean checked que la implementación podríadisparar.

En el caso de los métodos, los advices :

• No pueden declarar el disparo de una excepción que no está declarada en TODOS los joint pointssobre los que actua

• Pueden omitir algunas de las excepciones de tipo checked que han sido declaradas por alguno delos joint point sobre los que actua.

• Pueden declarar el disparo de excepciones más específicas (de tipo checked) que las definidas porlos joint point sobre los que está actuando.

• Pueden lanzar cualquier tipo de excepción de tipo runtime.

Page 21: Aspect Oriented Programming introduction

Aspect Oriented Programming

21

Diferencias

En comparación con los métodos, los advices:

• La declaración de un nombre es opcional.

• No pueden ser invocados directamente.

• No presentan especificadores de acceso (relacionado con la característica de que no pueden serinvocados directamente)

• No presentan un tipo de retorno en los advices de tipo before y after

• Tienen acceso a unas cuantas variables en el propio aspecto:thisJointPoint,thisJointPointStaticPart,thisEnclosingJointPointStaticPart

• Se puede utilizar la palabra reservada proceed en los advices de tipo around para ejecutar el jointpoint sobre el cual se está realizando el advice.

Análisis detallado de los advices

Hasta este momento disponemos de la información sobre las diferentes categorías de advices y susintáxis general. A lo largo de las siguientes subsecciones profundizaremos en cada uno de losdiferentes tipos de advices.

Before advice

Este tipo de advices se ejecutan antes de la ejecución del joint point sobre el que actúan. En el siguienteejemplo:

before():execution(@Secured * * (..)){ // asegurarse de que el usuario puede realizar la operación }

el advice realiza una comprobación de seguridad antes de que se produzca la ejecución de cualquiermétodo anotado con Secured.

En caso de que el advice dispare una excepción, el joint point no se ejecutará. Este tipo de aspectosson comunmente utilizados en aspectos tales como seguridad o trazabilidad.

After advice

Se ejecutan después de la ejecución del joint point sobre el que actuan. Dentro de esta categoría,AspectJ ofrece tres tipos de advices:

• Ejecución del advice independientemente del resultado de la ejecución del joint point.

• Ejecución del advice única y exclusivamente si el joint point ha finalizado correctamente.

• Ejecución del advice después que el joint point haya disparado una excepción.

Veamos en detalle cada uno de los tres tipos anteriores:

Advice After

Este tipo de advices se ejecutan independientemente del resultado de la ejecución del joint pointsobre el que actúan. Habitualmente se conoce a este tipo de advices como after finally puesto que susemántica es similar a la de un bloque finally.

El siguiente advice:

after(): call(@Logging * ServiceManager.*(..)){// registrar el resultado de la operación

Page 22: Aspect Oriented Programming introduction

Aspect Oriented Programming

22

}

registra el resultado de todas las operaciones de la clase ServiceManager que estén marcadas con laanotación Loggin, independientemente si retornan correctamente o terminan su ejecución de formainesperada mediante el disparo de una excepción.

Advice After Returning

En muchas ocasiones,será necesario ejecutar el código de nuestro advice única y exclusivamentecuando la ejecución del joint point haya terminado de forma correcta. Continuando con el ejemploanterior:

after () returning: call(@Logging * ServiceManager.*(..)){// registrar el resultado de la operación}

se seguirá registrando el resultado de las operaciones, siempre y cuando, la ejecución haya terminadocorrectamente, sin el disparo de ninguna excepción.

AspectJ ofrece una pequeña variante para este tipo de advices:

after() returning (ReturnType returnObject)

gracias a la cual se permite recuperar el objeto retornado por la ejecución del joint point dentro deladvice. Veamos un pequeño ejemplo ilustrativo:

after() returning (java.sql.Connection connection): call(java.sql.Connection DriverManager.getConnection(..)){ System.out.println("Se ha recuperado la conexión " + connection);}

Es importante tener claro que no se puede retornar un objeto nuevo (si que lo podemos modificar,pero no retornar uno nuevo).

Advice After Exception

Este tipo de advices son similares a los descritos en el apartado anterior. En este caso, el advice seejecutará única y exclusivamente cuando el joint point dispare una excepción. Presentan la siguienteestructura:

after() throwing:execution (* ServiceManager+.*(..))

El advice del ejemplo anterior se ejecutará siempre y cuando algún método de la clase ServiceManager(o alguna de sus subclases), dispare una excepción. En el supuesto de que la ejecución del joint pointtermine correctamente, este tipo de advices no serán ejecutados.

Al igual que los advices del apartado anterior, AspectJ ofrece una modo de recuperar la excepción queha sido disparada por el joint point de modo que esté disponible en el cuerpo del advice. Siguiendouna sintáxis similar a la anterior, tendríamos:

after() throwing (ExceptionType exceptionObject):

Un after throwing advice nunca podrá tragarse la excepción;por lo que seguirá subiendo por la pila dellamadas hasta llegar al objeto que realizó la invocación del joint point.

Around advice

Este clase de advices engloban al joint point, pudiendo ejecutar la lógica del mismo un númeroindefinido de veces. Incluso pueden omitir la ejecución del propio joint point. Algunos de los usosprincipales de este tipo de advices son los siguientes:

Page 23: Aspect Oriented Programming introduction

Aspect Oriented Programming

23

• Ejecución de lógica adicional antes y después de la ejecución de un joint point, como por ejemplo,acciones de profiling.

• Omitir la ejecución original, y realizar otra en su lugar, como por ejemplo, operaciones con cachés.

• Envolver la operación con una gestión de excepciones, con el objetivo de aplicar una política degestión de excepciones. Un ejemplo de este uso sería la gestión de transacciones.

Este advice ofrece una potencia superior a todos los advices vistos hasta el momento, puesto quepodrían sustituir a los anteriores. De todos modos, se considera una buena práctica utilizar el advicemás sencillo que cumpla las necesidades de la tarea que necesitamos llevar a cabo.

Ejecución del joint point

Si desde el around advice deseamos llevar a cabo la ejecución del joint point, tendremos que hacer usode la palabra reservada proceed() dentro del cuerpo del advice. Debemos recordar, que, puesto que lainvocación de proceed() ejecuta el joint point, tendremos que pasarle el mismo número de argumentosque han sido recolectados por el advice.

Asimismo, puesto que la invocación de proceed() supone la ejecución del joint point, el valor deretorno será el retornado por éste último.

Veamos un pequeño ejemplo de utilización de advices de este tipo:

void around(User user,int credits) throws InsufficientCreditsException: call(* User.pay*(int)) && target(user) & & args(credits){ try { proceed(user,credits); }catch(InsufficientCreditsException ex){ if(!processException()){ throw ex; } }

Analicemos en detalle la construcción anterior:

1. El pointcut selecciona cualquier llamada a los métodos de la clase User cuyo nombre comienze porpay y disparen una excepción de tipo InsufficientCreditsException

2. La segunda parte del pointcut recolecta el contexto del joint point: el usuario sobre el que se estárealizando la llamada y el número de créditos que se están pasando como argumento del métodoque se está ejecutando.

3. En el cuerpo del advice, se engloba la ejecución del método con un bloque de gestión deexcepciones, para realizar una protección adicional en caso de que se produzca una excepción. Enel caso de que la protección adicional no sea correcta, la excepción será disparada de nuevo.

Retornando valores

Todos los around advices deben declarar un valor de retorno (puediendo ser void). Habitualmente eltipo de retorno de éstos se corresponde con el tipo de retorno de los joint points sobre los que estáactuando.

En algunas ocasiones, todos los joint points sobre los que actua el advice no presentan el mismo tipo deretorno, como puede ocurrir cuando estamos añadiendo soporte transaccional a diferentes operaciones.En estas situaciones el tipo de retorno que debe declarar el advice será Object. AspectJ acomodará elvalor de retorno de acuerdo a las siguientes reglas:

• Si se está retornando un tipo primitivo, AspectJ realizará el boxing/unboxing correspondiente. Estacaracterística es similar a la incluida a partir de Java 5, pero AspectJ no precisa de dicha versiónde Java para realizar la operación.

Page 24: Aspect Oriented Programming introduction

Aspect Oriented Programming

24

• En el caso en el que el tipo de retorno no sea primitivo, AspectJ realizará los casts oportunos antesde retornar el valor.

Contexto del joint point

Muchas ocasiones es necesario acceder a los objetos que conforman la ejecución del joint point paraque el advice pueda llevar a cabo la lógica correspondiente. Por tanto, los pointcuts, necesitan exponerel contexto disponible en la ejecución del joint point de modo que pueda estar disponible en el cuerpodel advice. Dicho contexto puede definirse de dos modos diferentes:

• Objetos (incluyendo los tipos primitivos) que conforman el joint point

• Anotaciones asociadas al joint point

La siguiente tabla describe el cojunto de pointcuts que AspectJ ofrece para recuerar el contexto enlos joint points.

Table 1.14. Pointcuts para recuperar el contexto en un joint point

Pointcut Contexto recuperado

this(obj) Objecto this en el joint point que se está ejecutando

target(obj) Objetivo de la llamada en el joint point que se está ejecutando. En el casode un joint point de una llamada a un método, el target será el objeto querealiza la llamada. Para la ejecución de un método, el target será el objetothis. En los accesos a campos, el target será el objeto que se está accediendo.En el resto de joint points no existen un target disponible

args(obj1,obj2,...) Objetos que representa los argumentos en el joint point. Para las llamadas/ejecuciones de métodos/constructores, recupera los argumentos de losmismo. En el caso de los manejadores de excepciones, recupera laexcepción producida. Para los accesos en modo escritura a un campo,recupera el nuevo valor del campo.

@this(annot) Anotación asociada con el tipo del objeto this del joint point

@target(annot) Anotación asociada con el tipo del objeto target del joint point

@args(annot1,annot2,...)Anotación asociada con el tipo de los argumentos del joint point

@within(annot) Anotación asociada con el tipo "enclosing" del joint point

@withincode(annot) Anotación asociada con el método "enclosing" del joint point

annotation(annot) Anotación asociada con el asunto actual del joint point.

AspectosLos aspectos representan la únidad básica de modularización en el mundo de la orientación a aspectosen general, y en AspectJ, en particular. Los siguientes subapartados nos mostrarán una definición másformal que la vista hasta este momento.4

Analizaremos en detalle los aspectos, realizaremos una comparativa con las clases y veremos comonos pueden ayudar a modularizar y construir componentes reutilizables.

Trabajando con aspectos

Los aspectos son las construcciones encargadas de encapular la implementación de todos los conceptostransversales. Será el weaver el encargado de modificar el comportamiento del núcleo del sistema enfunción de la información definida en nuestros aspectos.

4Seguiremos analizando los nuevos conceptos, al igual que en las secciones anteriores, desde elpunto de vista de la sintaxis tradicional, dejandoun poco de lado la sintaxis @AspectJ

Page 25: Aspect Oriented Programming introduction

Aspect Oriented Programming

25

La sintaxis general de un aspecto es la siguiente:

[access specification][abstract] aspect <AspectName>[extends class or aspect] [implements interface-list][ [<association-speficier>(Pointcut)] | [pertypewithin(TypePattern) ] ]{ // aspect body}

La palabra reservada aspect permite realizar la declaración de un nuevo aspecto. Cada uno de estosaspectos presenta las siguientes características:

• Presenta un nombre para podere referirse a él desde otras partes del código.

• Puede presentar especificadores de acceso (public,proteced o private)

• Puede ser abstract

• Puede aplicar el mecanismo de herencia, derivando de otros aspectos o de clases tradicionales.Asimismo puede implementar interfaces.

• Puede especificar el modelo de instanciación

• Su cuerpo puede estar compuesto por definiciones de pointcuts, miembros o tipos anidados.

Diferencias con las clases

A la vista del apartado anterior, en un principio, parece que las clases y los aspectos son prácticamentelo mismo, pero no es así, los aspectos no son clases. A continuación se describen algunas de lasdiferencias principales:

Modelo de instanciación

Es el sistema el encargado de la instanciación de los aspectos. En resumen, nunca utilizaremos lapalabra reservada new para crear una instancia de un aspecto

Restricciones en el mecanismo de herencia

Los aspectos no pueden derivar de otros aspectos concretos, es decir, sólo pueden derivar de aspectosdefinidos como abstract. Esto es una restricción que se incluyó en la definición del lenguaje paraevitar complejidades innecesarias.

Parámetros genéricos

Los aspectos concretos no pueden declarar parámetros genéricos, sólo aquellos marcados comoabstract podran hacerlo. El motivo es el modelo de instanciación, puesto que, como los aspectos soninstanciados por el sistema, éste último no es capaz de realizar la inferencia de tipos.

privileged

Los aspectos pueden ser definidos con el especificador de acceso privileged, el cuál otorga la capacidadde acceder a los miembros privados de las clases sobre las que se está actuando.

ResumenNos hemos introducido en el mundo AOP, hemos analizado su evolución a lo largo a lo largo del HypeCycle, visto sus usos en el mundo real y hemos realizado un estudio de sus principales componentesy el modo en el que se utilizan cada uno de ellos.

Page 26: Aspect Oriented Programming introduction

Aspect Oriented Programming

26

Evidentemente, esto pretende ser un primer acercamiento al mundo de AOP, y concretamente aAspectJ, a través del cual el lector pueda comprender los beneficios de esta tecnología y le permitautilizarlo para escribir sus propios programas. Soy consciente de que se han quedado muchas cosas enel tintero, que darían cabida para un libro completo, por lo que a continuación se enumeran algunasde ellas para las mentes inquietas que deseen profundizar en otros aspectos que no tienen cabida eneste documento:

• Técnicas como static crosscutting tales como:

• Introducción de nuevos miembros en una clase

• Complemento de anotaciones

• Modificación de jerarquías de tipos

• Respuesta a errores y warnings en tiempo de compilación

• Debilitado de excepciones

• Asociación y predencia de aspectos

• Sintáxis @AspectJ

• Análisis detallado de los procesos de weaving

• Integración con Spring

• . . .

Para una análisis exhaustivo de estos y otros muchos aspectos, el usuario puede acudir a la secciónbibliografía

El objetivo de este introducción no era dar una visión teórica y aburrida de AspectJ sino dar una visiónpragmática del mismo. De este modo, la siguiente sección ilustrará la mayoría de conceptos vistosanteriormente mediante una serie de ejemplos reales.

Ejemplos realesHasta este momento hemos visto las posibilidades que nos ofrece AOP en general, y AspectJ enparticular, mediante la exploración de sus elementos, sintáxis y ejemplos sencillos. Los siguientessubapartados ofrecerán un conjunto de ejemplos reales de aplicación de la tecnología así como algunospatrones habituales.

La estructura de los ejemplos será la siguiente: se planteará un problema, se dará una solución general,y después se propondrá una alternativa basada en AOP y AspectJ. Pongámonos manos a la obra.

Patrón wormhole5

Este patrón consiste, básicamente, en habilitar un contexto de información desde un llamante a unllamado sin la necesidad de pasar dicha información como un conjunto de argumentos a lo largo detodas las invocaciones del los diferentes métodos del flujo de ejecución. Imaginemos por un momentoque estamos implementando un sistema de seguridad en el que cada uno de los métodos tiene quecomprobar quien les ha invocado para determinar si se les permite ejecutar la operación.

Creando un canal de comunicación directa entre dos niveles cualesquiera en la pila de llamadas,nos evitará tener que ir moviendo la información necesaria por cada una de las capas. De estemodo, evitaremos la necesidad de modificar la cadena de llamadas cuando necesitemos añadir algúnparámetro adicional al contexto de información.

5De nuevo, se ha optado por mantener la nomenclartura original del patrón, sin realizar una traducción al castellano, puesto que considero queel resultado de dicha traducción no resultaría demasiado intuitiva para el lector.

Page 27: Aspect Oriented Programming introduction

Aspect Oriented Programming

27

Solución tradicional

Sin la utilización de una tecnología como AOP disponemos de dos alternativas de solución. La primerade ellas movería toda la información necesaria a lo largo del contexto de llamadas añadiendo losparámetros que fueran necesarios, mientras que la segunda, haría uso de un almacenamiento espefícode los hilos.

La solución que pasa a través de parámetros el contexto de información necesario produce unacontaminación del API, puesto que cada uno de los métodos que intervienen en el flujo quetranscurre desde el llamante hasta el llamado necesitará de parámetros adicionales que permitan moverdicha información a lo largo de la pila de llamadas. La segunda solución propuesta, el uso de unalmacenamiento específico, pasaría porque el llamante crease una variable ThreadLocal en la que sealmacenase toda la información necesaria. Aunque esta segunda solución evita la contaminación delAPI, se necesita modicar tanto el llamante como el llamado, además de requerir un conocimiento decómo se almacena el contexto de información.

Descripción general

La siguiente figura ilustra la idea básica de este patrón arquitectónico:

Figure 1.5. Diagrama arquitectónico del patrón wormhole

La idea general consiste en indentificar dos pointcuts: uno en el llamado y otro en el llamante. Elprimero de ellos será el encargado de recolectar toda la información que será transmitida a lo largodel "aguejero de gusano". El segundo pointcut tendrá que especificar aquellos joint point del llamadoen los que debe actuar el wormhole.

En la imagen anterior cada una de las cajas trasnversales representa un nivel en la pila de llamadas.Habitualemente, para comunicar el llamante y el llamado tendríamos que ir pasando toda lainformación de nivel en nivel, hasta que alcanzásemos el nivel deseado. El patrón descrito en estasección establece un canal de comunicación directo a lo largo de todos los niveles de llamadas,evitando el paso de información nivel a nivel.

Plantilla

A continuación se propone una plantilla de solución que puede ser utilizada como base para laimplementación de este patrón en nuestros sistemas

Page 28: Aspect Oriented Programming introduction

Aspect Oriented Programming

28

public aspect WormholeAspect { pointcut callerSpace(caller context) : <caller pointcut> ; pointcut calleeSpace(callee context) : <callee pointcut> ; pointcut wormhole(<caller context>, <callee context>) : cflow(callerSpace(<caller context>)) && calleeSpace(<callee context<); // advices para el wormhole around(<caller context>, <callee context>) : wormhole(<caller context>, <callee context>) { // ... advice body } }

En la plantilla anterior, los dos primeros pointcuts recolectan los contextos en el llamante y en elllamado respectivamente. El tercero de ellos construye el wormhole entre los dos espacios, capturandotodos los joint point determinados por el pointcut calleeSpace que se encuentren en el flujo deejecución de aquellos joint points capturados por el pointcut callerSpace.

Puede que con un ejemplo nos queden las cosas un poquito más claras. Escribamos un pequeño aspectoque genere un canal de comunicación entre un sistema iniciador de transacciones y las ejecucionesde una query:

public aspect SqlTransactionAspect {

pointcut transactionSystemUsage(TransactionSystem ts) : execution(* TransactionSystem.*(..)) && this(ts) pointcut queryExecutions(SqlQuery query, String[ ] params) : this(query) && args(params) && execution(public * SqlQuery.exec*(String [ ])); pointcut wormhole(TransactionSystem ts, SqlQuery query, String[ ] params) : cflow(transactionSystemUsage(ts)) && queryExecutions(query, params);

before(TransactionSystem ts, SqlQuery query, String[ ] params) returning : wormhole(ts, query, params) { // realizar las operaciones deseadas }

• El pointcut transactionSystemUsage captura todos los joint point de ejecución en de la claseTransactionSystem. Además recolecta el objeto en si en el contexto de ejecución.

• El pointcut queryExecutions() captura todas las llamadas a los métodos exec de la clase SqlQueryy recolecta la propia query y los argumentos

• El pointcut wormhole genera un canal de comunicación directo entre el el sistema de transacciones yla ejecución de la query, capturando todos los joint points que se produzcan bajo el flujo de ejecuciónde transactionSystemUsage. Además, se captura el contexto de los dos pointcuts constituyentes.

• El advice que actua sobre el pointcut wormhole dispone ahora de toda la información: la query ysus parámetros así como el sistema de trasancciones

Page 29: Aspect Oriented Programming introduction

Aspect Oriented Programming

29

Hilos seguros

La amplia difusión de los procesadores con múltiples núcleos, el uso de lenguajes especialidados comoErlang o Haskell, y la popularidad de numeros libros al respecto, han logrado que los sistemas desoftware alcancen niveles de concurrencia insospechados hasta hace poco tiempo.

Si embargo, para muchos desarrolladores, incluso gente experimentada,la concurrencia supone unauténtico misterio. Implementar un sistema que presente un control de concurrencia es una tareacomplicada, dado que, en muchas ocasiones, los conceptos se difuminan a lo largo de diferentesmódulos. Estas circunstancias pueden ocasionar, la construcción de sistemas no demasiado ricos, conerros aparentes, caídas del sistema inesperadas, integridad comprometid, deadlocks, . . .

Por norma general, la implementación de un sistema de concurrencia basado en los patronesarquitectónicos y de diseño apropiados suele ocasionar sistemas mucho más fiables que los descritosen el párrafo anterior.

Muchos de los patrones de concurrencia presentan numerosos conceptos trasnversales, por lo que AOPpuede ayudarnos a simplificar su diseño y posterior implementación.

En este ejemplo, analizaremos el patrón read-write lock. La implentación clásica de este patrón suponela adición de código en todos aquellos métodos que necesiten modificar el estado de un objeto. Lossiguientes subapartados nos mostarán como podemos realizar una implementación modular de estepatrón basado en AspectJ.

Implementación tradicional.

Este patrón utiliza un par de bloqueos (locks): el bloqueo de lectura, y el bloqueo de escritura. Múltipleshilos lectores podrán adquirir el bloqueo de lectura siempre y cuando el bloqueo de escritura no hayasido adquirido. El otro bloqueo, el de escritura, únicamente podrá ser adquirido siempre y cuandoninguno de los hilos restantes haya tomado posesión del bloqueo de escritura.

La siguiente clase ilustra, mediante una pequeña clase de ejemplo, la solución anterior.

// package definition . . .

import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;

/*** @author migue* */public abstract class User { protected String username; protected String login; protected int credits; public User(int credits) { this.credits = credits; } private ReadWriteLock lock = new ReentrantReadWriteLock(); public void increaseCredit(int credit) { // adquirmos el bloqueo de lectura this.lock.writeLock().lock(); try {

Page 30: Aspect Oriented Programming introduction

Aspect Oriented Programming

30

// realizamos la operación, en este caso, // aumentar el crédito del usuario this.credits += credit; } finally { // liberamos el recurso adquirido this.lock.writeLock().unlock(); } } public void decreaseCredit(int credit) { // adquirmos el bloqueo de lectura this.lock.writeLock().lock(); try { // realizamos la operación, en este caso, // disminuir el crédito del usuario this.credits -= credit; } finally { // liberamos el recurso adquirido this.lock.writeLock().unlock(); } } public boolean hasCredit() { // adquirimos el bloqueo de lectura this.lock.readLock().lock(); boolean hasCredit; try { hasCredit = this.credits > 0 ? true : false; } finally { this.lock.readLock().unlock(); } return hasCredit; } }

Resulta evidente que la manera anterior de realizar los bloqueos resulta intrusiva, puesto que para cadauno de los métodos para los que en los que se desee gestionar la gestión de la concurrencia, tendremosque añadir los fragmentos de código vistos en el ejemplo. Cualquier método en el que nos olvidemosde añadir el código de gestió de la concurrencia puede ocasionarnos un incorrecto funcionamiento denuestro sistema. Además, debemos asegurarnos que si un método adquire el bloqueo de lectura, seaeste el que libere, y no el de lectura, y viceversa.

Implementación basada en AspectJ

Esta alternativa de solución propone a creación de un aspecto que encapule toda la lógica del patróndescrito; evitando de este modo la modificación de todas aquellas clases que necesiten hacer uso dediho patrón. Puesto que además, el patrón es reutilizable en numerosas situaciones, haremos que elaspecto también lo sea.

La base de la solución, tal y como se indicaba anteriormente, consiste en disponer de un aspectoabstracto que implemente toda la lógica del patrón:

public abstract aspect ReadWriteLockSynchronizationAspect

perthis(readOperations() || writeOperations()) {

Page 31: Aspect Oriented Programming introduction

Aspect Oriented Programming

31

public abstract pointcut readOperation(); public abstract pointcut writeOperation(); private ReadWriteLock lock = new ReentrantReadWriteLock(); Object around(): readOperation(){ this.lock.readLock().lock(); try{ return proceed(); }finally{ this.lock.readLock.unlock(); } }

Object around(): writeOperation(){ this.lock.writeLock().lock(); try{ return proceed(); }finally{ this.lock.writeLock.unlock(); } } }

Analicemos con un poquito más de detalle la definición del aspecto anterior:

1. En primer lugar, mediante la asociación de aspectos6, asociamos una instancia de nuestro aspectocon cada uno de los objetos que concuerden con los criterios establecidos en los pointcutsreadOperations y writeOperations. Nótese que una nueva instancia de nuestro aspecto será creadacada vez que se prduzca un matching. El uso de la asociación nos permite introducir, en las clasesque requieren sincronismo, el objeto de lock, sin necesidad de conocer el tipo de las mismas.

2. El pointut abstracto obligará que los aspectos hijos lo tengan que definir, capturando con él todaslas llamadas a los métodos que necesitan sincronismo y no modifican el estado del objeto.

3. De modo similar al anterior, el pointcut writeOperations, capturará todas las llamadas a los métodosque necesiten realizar una modificación en el objeto.

4. Puesto que cada matching que se produzca generará una nueva instancia del aspecto para cadaobjeto this diferente, cada elemento de sinronización estará asociado con el objeto sobre el que seestá realizando el advice.

5. El around advice readOperation adquiere y libera el bloqueo de lectura.

6. Del mismo modo, writeOperation, adquiere y lbera el bloque de escritura.

Ahora que tenemos preprada nuestros aspecto base, realizemos una implementación concreta.

Implementación de subaspectos

La habilitación de este patrón requiere la implementación de un aspeto concreto que ponga en juegolas clases sobre las que deseamos establecer un control de la concurrencia. Dado que los aspectosconcretos tendrán que marcar qué metodos son de lectura y escritura, el uso de anotaciones que nossimplifiquen la selección suele ser una buena idea. Por tanto, defininiremos la siguiente anotación paramarcar los métodos de lectura:

Page 32: Aspect Oriented Programming introduction

Aspect Oriented Programming

32

@Target(ElementType.METHOD)public @interface ReadOnly{}

Del mismo modo definiremos una anotación para marcar los métodos de escritura:

@Target(ElementType.METHOD)public @interface ReadWrite{}

Además, necesitamos definir una anotación que nos indique cuando estamos utilizando el patrón.

@Target(ElementType.TYPE)@Inheritedpublic @interface ReadWriteLockManaged

Ahora estamos listos para definir el aspecto,basado en las anotaciones anteriores, que nos aplique elpatrón read-write lock.

public aspect AnnotationDrivenReadWriteAspect extends ReadWriteLockAspect {

public pointcut readWriteLockManaged(): execution(* (@ReadWriteLockManaged *).*(..) ); public pointcut readOperation() : execution(@ReadOnly * *(..)) && readWriteLockManaged(); public pointcut writeOperation() : execution(@ReadWrite * *(..)) && readWriteLockManaged();}

Analicemos en detalle la construcción del aspecto anterior:

1. El pointcut readWriteLockManaged captura todas las llamadas a los métodos de aquellas clasesque se encuentren marcadas con la anotación AnnotationDrivenReadWriteAspect

2. El pointcut readOperation complementa al anterior, seleccionando únicamente, de todos losmétodos capturados por readWriteLockManager, aquellos que se encuentren anotados conReadOnly

3. De un modo similar al anterior, el pointcut writeOperation, captura únicamente aquellos métodosdescritos con la anotación ReadWrite.

Ahora llega la parte más divertida de esta sección. Apliquemos nuestra nueva construcción sobre elejemplo analizado en implementación tradicional:

// package definition . . .

import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;

/*** @author migue*

Page 33: Aspect Oriented Programming introduction

Aspect Oriented Programming

33

*/@ReadWriteLockManagedpublic abstract class User { protected String username; protected String login; protected int credits; public User(int credits) { this.credits = credits; } @ReadWrite public void increaseCredit(int credit) { this.credits += credit; } @ReadWrite public void decreaseCredit(int credit) { this.credits -= credit; } @ReadOnly public boolean hasCredit() { return this.credits > 0 ? true : false; }}

Comparemos este listado con la implementación tradicional realizada anteriormente . ¿No resultamucho más comprensible?

Evidentemente, aunque esta es una buena solución, existe un acoplamiento entre la anotación@ReadWriteLockManaged, que una clase indique su participación en el patrón puede no ser deseable,si dicha clase se utiliza en múltiples sistemas.

El problema anterior podría solucionarse mediante la inclusión de un aspecto que introdujese laanotación en los tipos indicados.7

Veamos un aspecto que introduciría la anotación indicada en las clases que la requieran, de este modoevitaremos el acoplamiento entre la clase y la anotación que aplica el patrón.

public aspect InventoryReadWriteLockParticipation { declare @type: User: @ReadWriteLockManaged;}

El aspecto anterior anotaría la clase User con la anotación ReadWriteLockManaged. De este modo, laanotación de cualquier clase no requeriría más que la modificación de este aspecto, para que detectaseaquellas clases susceptibles de estar bajo la gestión de concurrencia.

BibliografíaAl igual que en el resto de capítulos, se incluye una referencia bibliográfica específica que permitiráal lector profundizar en la temática introducida:

• AspectJ Programming Guide [http://www.eclipse.org/aspectj/docs.php]

• AspectJ in Action

7Aunque no hemos visto la introducción de tipos, se ha decidido incluir un pequeño aspecto de ejemplo.

Page 34: Aspect Oriented Programming introduction

Aspect Oriented Programming

34

• AspectJ in Action Second Edition: Enterprise AOP with Spring Applications

• Spring AOP reference [http://static.springsource.org/spring/docs/2.0.8/reference/aop.html]

• Eclipse AspectJ. Aspect-Oriented Programming with AspectJ and the Eclipse Aspect - AddisonWesley - 2004

• John Wiley And Sons Mastering Aspectj Aspect-Oriented Programming in Java

• AspectJ.Cookbook - OReilly - 2004

• Mastering AspectJ - Wiley