Compatibilidad

AspectJ es una extensión compatible de Java para facilitar el uso de aspectos por parte de los programadores de Java. Por compatible se entiende:

Compatibilidad base

Todos los programas válidos de Java deben ser programas válidos de AspectJ.

Compatibilidad de plataforma

Todos los programas válidos de AspectJ deben correr sobre la máquina virtual estándar de Java.

Compatibilidad de programación

La programación en AspectJ debe ser una extensión natural de la programación en Java.

Esta última meta fue una de las guías más importante a la hora de tomar decisiones sobre el lenguaje. Es estáticamente tipado y usa el sistema de tipos estático de Java.

Instalación

Prerrequisitos:

Tener instalado Java JDK y JRE. En este caso se enseñará a instalar AspectJ en Intellij para un sistema operativo Windows

Semántica

En sí, AspectJ funciona extiendiendo a Java como Base para soportar el manejo de aspectos y clases, agregando a la semántica de Java cuatro entidades principales.

Los puntos de enlace (Join Points)

Son puntos bien definidos en la ejecución de un programa, entre ellos podemos citar llamadas a métodos y accesos a atributos.

Los cortes (Point Cuts)

Agrupan puntos de enlace y permiten exponer el contexto en ejecución de dichos puntos. Existen cortes primitivos y también definidos por el usuario.

Los avisos (Advices)

Son acciones que se ejecutan en cada punto de enlace incluido en un corte. Los avisos tienen acceso a los valores expuestos por el corte. Las tres entidades anteriores son dinámicas porque permiten definir comportamiento adicional que actuará en tiempo de ejecución.

Las introducciones y declaraciones (Inter-Type Declarations)

Permiten cambiar la estructura de clases de un programa agregando o extendiendo interfaces y clases con nuevos atributos, constructores o métodos. Esta última entidad es estática porque afecta la signatura estática del programa.

Semantica De Declaración

[ privileged ] aspect Id [ extends Type ] [ implements TypeList ] [ Per Clause ] { Body }

Un Aspecto puede ser declarado como cualquier clase de Java, con su id, con la palabra reservada "aspect", con sus respectivos modifiers para modificar el acceso y comportamiento de la clase, e introduciendo nuevos elementos a la semántica de cómo funcionan y van a interactuar con respecto a las demás clases de nuestro proyecto. De estas nos enfocaremos en 3 en especial debido a su particularidad con los Aspectos:


Un modifier especial que, como su nombre nos lo indica, le dará privilegios al aspecto, esto significa que nos permitirá poder acceder a métodos y atributos privados de clases y aspectos externos.


Un aspecto puede extender una clase, u otro aspecto abstracto y puede implementar tantos interfaces como se le indiquen.

La siguientes son unas reglas a tener en cuenta:

  • De un aspecto a pesar de extender una clase no se puede crear una instancia del mismo con el método new.
  • Una clase no puede extender un aspecto.
  • Un aspecto no puede extender un aspecto que no sea abstracto.

Los Aspectos originalmente se generan como singleton. Sin embargo, pueden haber varias formas de crear diversas instancias del mismo acceso, según su objeto asociado, su posición de ejecución, entre otras. Las Per Clause son quienes se encargan de modificar los Aspectos para poder tener más control sobre la cantidad y comportamiento de los Aspectos

Sin embargo, no se recomienda mezclar varios de estos métodos debido a que pueden llegar a inteferir con flujos ajenos de los distintos Aspectos.

Compiladores diseñados para AspectJ

Los dos principales compiladores para AspectJ son:
  • ajc ajc parte de las herramientas soportadas por el proyecto Eclipse
  • abc que es un compilador, que optimiza y es extensible, producido en aspectbench.org.

Objetivos

La intención de AspectJ es ser un LOA práctico, que provea un conjunto sólido y maduro de características orientadas a aspectos, compatible con Java para aprovechar su popularidad.

Lenguaje

Aspect

Es la unidad central de Aspectj, se puede colocar en un archivo .aj.Contiene el código que expresa las reglas de los crosscutting.Un aspecto es una unidad de modularización en AOP como las clases son en OOP.

PointCut

Una palabra del lenguaje que selecciona los puntos interesantes (join points) y colecta el contexto de este punto. Selecciona puntos interesantes de la ejecución. Pueden ser llamadas, ejecuciones, instanciar objetos, constructores, manejo de excepciones.

Tipos de point cuts

tabla de pointcut tabla de pointcut

Mas informacion

PointCut Pattern

Advice

Código que se ejecutará cuando se llegue al pointcut este se puede definir de diferentes maneras. Existen tres tipos de advice:

  • before()
  • after()
  • around()

Before

Se ejecuta antes de cada join point.

After

Se ejecuta después de cada join point. Puede de tres tipos:

  • Defecto: el cual retorna sin importar el resultado.
  • Returning: Me realiza la acción únicamente si finalizó correctamente y/o me retornó el valor (Este Advice también puede servir con JointPoints que sean voids). Este returning me permite también utilizar los valores retornados por los JoinPoints para utilizarlos en los advices.
  • Throwing: Me realiza la acción únicamente si la acción del PointCut finalizó lanzando una acción o un resultado como una excepción.

Around

Se ejecuta en lugar de el join point. Debe ser declarado con un tipo de retorno.

El código del join point se puede ejecutar usando la palabra proceed();



Atributos de los advice

thisJoinPoint : Representa el join point en el cual el advice se está ejecutando. thisJoinPointStaticPart : equivalente a thisJoinPoint.getStaticPart() pero consume menos recursos. thisEnclosingJoinPointStaticPart : la parte estatica de la dinamica que encierra el join point.

Particularidades

Sintaxis de las notaciones

Aspect

aspect

PointCut

pointcut

Advice before

before

Advice after

after

Advice around

aspect

Tutorial

A partir de una aplicación de un banco se desea implementar un Log de transacciones y un sistema de login mediante programación orientada a aspectos. Para esto se tienen las siguientes clases en las cuales se implementa la funcionalidad sencilla de un banco.

Adicionalmente se tiene la siguiente clase la cual representa a los usuarios de este banco.

Aspectos

Se implementarán dos aspectos uno llamado Login y otro llamado Log.

Ahora debemos identificar los join points de nuestra aplicación para poder implementar los pointcuts en los aspectos.

Identificacion de los puntos de corte de los aspectos

Esta es la funcionalidad que queremos guardar en el log de transacciones.

Esta es la funcionalidad que queremos aplicarle un login. Aunque hay join point que son comunes por buena practica los viviremos en dos aspectos.

En el primer punto de corte queremos capturar los metodos que comiensen con make y my.

Queremos capturar las distintos tipos de transacciones. Posteriormente agregamos los advices que queremos en los dos aspectos con su funcionalidad correspondiente.

Queremos que escribir el los se realice depues de que la transacción se haya realizado, por esta razón elegimos after.

Queremos que el login sea antes de la transacción se haya realizado, por esta razón elegimos before. Este es un ejemplo muy sencillo de lo que nos permite aspectj.

Finalmente este código nos agrega la funcionalidad de un login antes de las transacciones y un registro de sus actividades en un archivo.

Sistema de inventario con log

En este tutorial vamos a ver el paso a paso de cómo subir a la nube un servidor para el control de inventarios. Es una API Rest y se utiliza el entorno de trabajo Spring. Vamos a ver la estructura del proyecto, las clases y cómo subirlo a un nodo de AWS con Putty. También veremos cómo hacer peticiones al servidor mediante Postman.
Para acceder y descargar el proyecto, ir al siguiente enlace https://github.com/esgonzalezca/SpringLenguajes

Estructura del proyecto

Entramos a src/main/java/com/spring/aop/api/

Advice

Dentro de este directorio está la clase que contiene los pointcuts para la petición GET (myPointCutGet) y para la petición POST (myPointCutPost). Ambos son de tipo execution.
Después están las dos funciones que se usarán para hacer los logs:applicationLoggerPost para las peticiones POST, donde se crea un ObjectMapper, se obtiene el nombre del método, el nombre de la clase y los argumentos para registrar la información en el log. Luego con pjp.proceed() se ejecuta el JoinPoint. Esta función tiene la anotación
@Around porque reemplaza el código que está en el joinpoint
La segunda función applicationLoggerGet cumple prácticamente la misma función de applicationLoggerPost pero como tiene la anotación @AfterReturning recibe el retorno del pointcut (myPointCutGet) en la variable redVal y luego hace el registro en el log.

Model

En la clase Product se describen los atributos de los productos que estarán en nuestro repositorio, los constructores, getters y setters.

Service

En la clase ProductService se inicia la base de datos y se hacen las operaciones de consulta y adición de registros.

Controller

En la clase ProductController es donde se expone la información con REST, hay una petición POST (save) para guardar un producto o una lista de productos.
La petición GET (findProducts) para obtener todos los productos en el sistema.
En esta clase usamos la clase ProductService para acceder a la base de datos.

Repository

La clase ProductRepository hereda de JpaRepository, hay que declarar la tabla con Producto y el tipo de dato de la llave primaria (Integer).

Y por último, fuera de los directorios vistos arriba, está la clase SpringAopApplication, donde está el método main para correr el servidor.

Creación del .jar

Usaremos el IDE Netbeans.

En la parte superior de la pantalla haremos clic en el icono del Martillo con la escoba. Así se creará un archivo .jar con un nombre genérico (el cual se puede cambiar más adelante) en la carpeta “Target” de nuestro directorio del proyecto en local.

Creación del Dockerfile

Ahora crearemos un archivo llamado “Dockerfile” que no tendrá extensión y tendrá este contenido:

Nótese que aquí “myService.jar” es como se debe llamar el archivo ejecutable de Java. Este archivo debe estar en la misma carpeta del Dockerfile ya que será transportado a la carpeta /opt/app de nuestro entorno virtual (nodo de AWS). Recuerde que este archivo .jar fue generado al principio dentro de la carpeta target de nuestro proyecto en local.

Creación del nodo EC2

Nota: Para esta sección se usó una máquina t2.micro de AWS (se puede acceder a una de estas máquinas con la capa gratuita de AWS).

Vamos a la página de AWS https://aws.amazon.com/ , creamos una cuenta y accedemos a la consola.

Vamos a la sección EC2

Vamos a la sección instances y oprimimos Launch instance.

img src="https://i.imgur.com/LI3czvB.png" alt="">

Seleccionamos Amazon Linux 2 64 bits(X86) y luego en “Select”.

Seleccionamos la t2.micro.

Luego hacemos click en “Review and Launch”.

Hacemos click en Launch. A continuación nos pedirá ingresar un nuevo valor de llave. Ingresamos los datos como sale a continuación.

Acceder al nodo usando Putty

Ya con la llave del nodo, accedemos a él mediante Putty. Descargar en: https://www.putty.org

Interfaz inicial de Putty

En el cuadro de Host Name ingresamos la IP del nodo del nodo que creamos unos pasos arriba. Para el caso de la exposición hecha en clase:

Luego vamos a la categoría SSH - Auth.

En el campo Private key file for authentication ponemos la ruta de la llave del nodo de AWS. Luego regresamos a la categoría Session y oprimimos open.

Accedemos con el usuario ec2-user (es el usuario por defecto).

Desde esta ventana de comandos instalamos docker para hacer el contenedor para correr nuestra API.

Iniciamos docker.

Luego vamos a la carpeta donde está el Dockerfile.

Construimos el contenedor.

Corremos el contenedor.

Ya está corriendo el servidor, debajo comenzarán a aparecer los logs.

Peticiones al servidor con Postman

Enlace para descargar Postman: https://www.postman.com/downloads/

Agregamos una nueva petición de tipo GET para obtener la lista de productos de nustro inventario. En la dirección escribimos la ip del nodo seguida por “:” el puerto “/” findProducts. Damos click a Send para enviar la petición al servidor.

Log del servidor.

Ahora agregamos otra petición de tipo POST para agregar productos al inventario. Ingresamos la misma ruta cambiando lo que va depués del “/” por save. En la pestaña Body seleccionamos raw y JSON para escribir el cuerpo de la petición (los artículos que vamos a agregar). Enviamos la petición son Send

Log del servidor

Luego hacemos otro GET para obtener la lista de productos actualizada.

Log del servidor

Queremos hacer un CRUD de estudiantes en donde se pueda mostrar Logs dependiendo de que función llamemos en el main.
Todo el codigo presentado esta en el Siguiente Github
Main Vamos a hacer distintos puntos de corte para:
  1. Funciones de la clase Repository, Service y RestController
  2. Spring Beans
Vamos a realizar advices para cuando:
  1. Lance una excepción en cualquiera de los metodos propuestos
  2. Entre a una función
  3. Salga de una función
  4. Entre a una función con parametros invalidos
Se desea hacer un sistema en el cual se pueda modelar una veterinaria con ciertas funciones donde se puedan pedir citas.
Todo el código presentado está en el siguiente link: Github.
Main Vamos a hacer distintos puntos de corte para las funciones donde hay crosscutting:
  1. MakeAppointment
  2. Update Level
Vamos a realizar advices para cuando:
  1. Se deba verificar si la mascota es elegible para pedir una cita
  2. Entre a una función
  3. Salga de una función

Ejemplos

Hello World

Ejemplo más sencillo de AspectJ.

Clase TestAsp

La clase en la cual tenemos unos cuantos metodos y un main.

Aspect Aspect

Nuestro aspecto con algunos puntos de corte para ver su funcion.

Comodines

Calls y Execution

Calls vs Execution

La diferencia entre calls y execution es que calls se refiere al acto de llamar a una función, mientras que execution se refiere al acto de ejecutar el código de una función.

En otras palabras, calls es el evento de pasar el control a una función, mientras que execution es el proceso de ejecutar las instrucciones de una función.

Por ejemplo, la siguiente línea de código:

int x = add(1, 2);

contiene una llamada a la función add(). Cuando se ejecuta esta línea de código, el control se pasa a la función add(). La función add() entonces ejecuta sus instrucciones, que en este caso son:

int sum = x + y;

return sum;

El proceso de ejecutar las instrucciones de la función add() se conoce como ejecución.

Context Passing

Aspect Behaviours

Main Seguridad

Diferentes usuario realizan transacciones

Clase Seguridad

Define si un usuario tiene acceso

Aspecto Seguridad

Aspecto en que se define si un usuario tiene permisos

Main productos

Uso de diferentes metodos de productos

Clase productos

Clase de productos donde se definen sus metodos

Aspecto productos

Aspecto define el tiempo de ejecucion en cualquier metodo

Main pedido

Uso de diferentes metodos para poder realizar un pedido

Clase Pedido

Clase de pedido donde se definen sus metodos

Clase inventario

Clase de inventario donde se definen sus metodos

Clase inventario helper

Clase de InventarioHelper donde se definen sus metodos, ayuda en la actualizacion de los aspectos de inventario

Aspecto Actualizacion del stock

Aspecto que se encarga de la logica de la actualizacion del stock

Aspecto Registro Actividad

Aspecto que se encarga de registrar los productos agrgados y eliminados

Aspecto Verifica Stock

Aspecto se encarga de revisar si existe suficiente stock del producto

Clase Calculadora

A continuación se presenta la clase calculadora con los métodos básicos.

Aspecto LogCal

Aspecto que realiza los logs respectivos.

Clase Main

Clase Main de la calculadora.

Ventajas y Desventajas

Ventajas

  • Facilita/mejora la modularidad de los desarrollos de software.
  • El código es organizado y comprimido
  • Es reutilizable
  • Añade constructores a Java que permiten la implementación modular de crosscutting concerns
  • Permite modelar referencias transversales, extiende las capacidades de POO\

Desventajas

  • Puede introducir nuevos errores y fallas de seguridad si no se implementa adecuadamente
  • El paradigma puede emplearse mal quitando y/o delegando responsabilidades a ciertas clases
  • Los Aspectos pueden ser mal utilizados. Un programador puede implementar una falsa funcionalidad en cualquier estado del desarrollo y afectar a un amplio rango del sistema.

Contribudores

2016-1

  • Sergio Alejandro Diaz Pinilla
  • Pedro Luis Monroy Garces
  • Jefferson Javier Hernández Panqueba

2016-2

  • Juan Rodriguez Duran
  • Johann Triana Olaya
  • Jonatan Parra Toro

2017-1

  • Juan Sebastián Martínez Beltrán
  • Andrés Felipe Sánchez Lemus

2019-2

  • Juan Sebastián Becerra Barcenas
  • Juan Sebastián Peña Quintero
  • Brayan David Vega Triana

2020-1

  • Andres Esteban Romero Romero
  • Oscar Andres Mancera Garzón
  • Yerson Andres Valderrama Ceron

2020-2

  • Sergio Esteban González Cárdenas
  • Elsa Johanna Arias Muñoz
  • Nicolás Alejandro Contreras
  • Hubert Alejandro Tovar Strubinger

2021-1

  • Verbo Sebastián Camacho Silva
  • Miguel Alejandro Peña Hurtado
  • Diego Fernando Pastás

2022-1

  • Ángel Mateo González​
  • Rubén Darío Guarnizo​
  • Lorraine Rojas Parra​
  • Alejandra Superlano Esquibel​

2022-2

  • Kevin Leonardo Alvarez Mora
  • Jose Francisco Lugo Nomesque
  • Andres Yohany Velasquez Martinez
  • Valentina Viafara Esteban

2023-1

  • Angel Guillermo Peñarredonda Silva
  • Manuel David Maya Rosero
  • Nicol Estefania Guerrero Gutierrez

2023-2

  • Juan Pablo Garzon Parra
  • Brayan Sebastián Yepes Garcia
  • Diego Sebastián Rubiano Ballén
  • Joe Zafir Mendez Leon

Bibliografía

  • Libro: Mariano Lorente López, Fernando Asteasuain, Bernardo Ezequiel Contreras. (2005). Programemos en AspectJ.
  • https://sistemasacademico.uniandes.edu.co/~miso4204/dokuwiki/lib/exe/fetch.php?media=temas:aspectj.pdf
  • http://ldc.usb.ve/~yudith/docencia/ci-4822/presentacionPOA.pdf
  • https://es.wikipedia.org/wiki/AspectJ
  • https://eclipse.org/aspectj/
  • Constantinides, C. (2015). V Aspect-Oriented Programming with AspectJ. En Principles of Programming Languages (págs. 309-407). Montreal: Concordia University.
  • eclipse. (Abril de 2020). The AspectJ Language. Obtenido de The AspectJ Programming Guide: https://www.eclipse.org/aspectj/doc/released/progguide/language-joinPoints.html
  • Fernández Egido, A. (Junio de 2009). CORE. Obtenido de CONFLICTOS ENTRE ASPECTOS EN LA PROGRAMACIÓN ORIENTADA A ASPECTOS : https://core.ac.uk/download/pdf/29400487.pdf
  • IBM. (1 de Enero de 2002). IBM. Obtenido de Improve modularity with aspect-oriented programming: https://www.ibm.com/developerworks/library/j-aspectj/index.html
  • Laiseca Manso, X. (2007 de Julio de 27). MORElab. Obtenido de Cursillo 2007: http://e-ghost.deusto.es/docs/2007/cursillos/aop/curso_aop.pdf
  • Lorente Lopez, M., Asteasuain, F., & Contreras, E. B. (2005). Programemos en AspectJ. programemos.
  • Colyer, A., Clement, A., Harley, G., & Webster, M. (2004). Eclipse AspectJ: Aspect-Oriented Programming with AspectJ and the Eclipse AspectJ Development Tools. Addison Wesley Professional
  • .
  • Eclipse Foundation. (Año). AspectJ Documentation. Recuperado de https://eclipse.dev/aspectj/sample-code.html#declares-exceptionSpelunking
  • Laddad, R. (2009). Aspectj in action: enterprise AOP with spring applications. Simon and Schuster.