RSS

AOP – Programación Orientada a Aspectos

31 Mar

La programación orientada a aspectos (AOP) es una metodología que sirve para complementar a la programación orientada a objetos clásica (OOP).La OOP es muy útil para implementar la lógica de nuestra aplicación. Sin embargo se ve limitada a la hora de incluir una serie de funcionalidades que se usan en diferentes puntos en nuestra aplicación y que en inglés se conocen como crosscutting concerns. Entre estos elementos podrían estar trazar nuestra aplicación (logging), el cacheo de la información o la validación de los argumentos en los distintos métodos.

crosscuttingconcerns

Igual que en la OOP el elementos básico es el objeto (clase), en la AOP el elemento básico es el aspecto (vaya ocurrencia🙂 ). Hay varios frameworks AOP en el mercado pero de todos ellos el más usado es AspectJ. Además tenemos un framework en Spring llamado Spring AOP que está enfocado a manejar los croscutting concerns para los beans que se han declarado en nuestro contenedor IoC. En nuestra aplicación Spring podemos beneficiarnos tanto del uso de AspectJ como de Spring AOP en función de las necesidades.

¿Comó soluciona la programación orientada a aspectos los problemas con los crosscutting concerns?.
Como ya hemos comentado OOP no logra manejar cierta funcionalidad de nuestras aplicaciones (logging, cacheo, validación) con la flexibilidad que requiere. Intentar tratar estas funcionalidad con OOP en las clases de nuestra aplicación puede dar lugar a código spaguetti y problemas de scattering.
La solución que propone AOP es elegante a la par que eficaz. Se basa en el patrón de diseño estructural proxy dentro de los patrones de diseño de GoF (Gang of Four).
El fundamento del patrón de diseño proxy es simple, el objeto inicial sobre el que vamos a querer hacer la funcionalidad de logging, cacheo, validación, … está encapsulado por un objeto proxy. Cualquier llamada realizada al objecto inicial será interceptada y redirigida al proxy. Será este objeto proxy el que se encargue de realizar toda la funcionalidad asociada a los crosscutting concerns primero y después pasará el control a nuestro objeto inicial que será el que realice la lógica de negocio necesaria. Creo que la siguiente imagen sirve para explicar muy bien el funcionamiento del patrón proxy.

funcionamiento proxy

Hay dos formas de implementar el patrón proxy:
Proxy estático. Se define un proxy especifico que encapsula cada llamada a un método.
Proxy dinámico. Se crea un proxy valido para cualquier objeto que sea instancia de una clase que a su vez implemente una determinada interfaz. Esta interfaz tendrá definidos una serie de métodos que serán los que sean interceptados por nuestro proxy. Los proxies dinámicos son creados mediante la API de Java Reflection.

Ejemplo de proxy dinámico.

JavaReflection nos da la interfaz InvocationHandler como primer paso. Esta interfaz tiene definido un método invoke que tiene como primer argumento el objeto proxy que se hará cargo de la llamada a nuestro método y como segundo el método que realmente queremos llamar.

public interface InvocationHandler {
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

Tendremos que implementar esta interfaz por una clase que por ejemplo se encargue de la funcionalidad de logging para nuestros métodos. El objeto inicial (target) que se quiere interceptar por el proxy podemos pasarselo a nuestra clase vía constructor.

public class ManejadorLogging implements InvocationHandler {
	private Object target;
	public ManejadorLogging(Object target) {
		this.target = target;
	}
	public Object invoke (Object proxy, Method method, Object[] args) throws Throwable {
		log.info("Se va a llamar al método " + method.getName());
		Object resultado = method.invoke(target,args);
		log.info("Se  ha llamado al método " + method.getName());
		return resultado;
	}

Para probar el funcionamiento de nuestro proxy que intercepta a una clase que se encarga de sumar dos números binarios tenemos que crear nuestro proxy llamado al método estático Proxy.newProxyInstance:

public class Prueba {
	public static void main(String[] args) {
		Calculadora calculadoraBinaria = new CalculadoraBinaria();
		Calculadora calculadora = (Calculadora) Proxy.newProxyInstance(
                                  calculadoraBinaria.getClass().getLoader(),
                                  calculadoraBinaria.getClass().getInterfaces(),
                                  new ManejadorLogging(calculadoraBinaria));
		calculadoraBinaria.suma("010","011");
	}
}

La ejecución del método quedará interceptada por el método invoke del ManejadorLoggin, el cual guardará una entrada en el log, llamará, ahora sí, al método que realizará la suma binaria y finalmente añadirá otra entrada al log.

 
Deja un comentario

Publicado por en 31 marzo, 2011 en Spring

 

Etiquetas: , , ,

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: