Spring AOP Versión 2.x 4 de Abril de 2008 1 SPRING FRAMEWORK 2.X
Spring -AOP 2 SPRING FRAMEWORK 2.X
3 SPRING FRAMEWORK 2.X Croscutting Concern
Introducción AOP Con programación orientada a objetos las posibles soluciones para implementar estos crosscutting concern (asuntos de carácter universal) pasan por la herencia y la delegación. Con la herencia se puede llegar a una jerarquía de objetos complicada. Con la delegación la solución es complicada y requiere de llamadas duplicadas al objeto delegado. AOP permite definir la funcionalidad común en un único punto. Declarativamente se define cómo y dónde esta funcionalidad es aplicada sin la necesidad de modificar la clase a la que aplicas la nueva funcionalidad. 4 SPRING FRAMEWORK 2.X
Terminología AOP Aspect: Funcionalidad genérica que se está implementando. Ej: Seguridad, logging, etc Joinpoint: Punto de la ejecución de un programa donde un aspecto puede ser introducido. Advice: Implementación actual de un Aspect. Pointcut: Define en qué joinpoints va a ser aplicado el advice. Normalmente se indicará clases explícitas y un nombre de método, pero también es posible definir expresiones regulares que definen patrones para nombres de clases y nombres de métodos. Además es posible en algunos AOP frameworks definir un pointcut en tiempo de ejecución. 5 SPRING FRAMEWORK 2.X
6 SPRING FRAMEWORK 2.X Terminología AOP (II)
Terminología AOP (III) Introducción: Permite añadir atributos y métodos a clases existentes. Ejemplo: Auditable advice Target:Clasealaqueseleaplicaunaspecto. Proxy:Eselobjetocreadodespuésdeaplicarunaspectoaunobjetotarget. Weaving: Es el proceso de aplicar aspectos a objetos targets para crear un nuevo objeto proxy. Los aspectos son tejidos (woven) dentro de los objetos target en los especificados joinpoints. El proceso de tejido puede realizarse en los siguientes momentos: Tiempo de compilación: Requiere un compilador especial. Tiempo de carga de clase: Aspectos son tejidos cuando el objeto target es cargado dentro de la JVM. Requiere un classloader especial que aumente el bytecode de la clase target antes de que la clase sea introducida dentro de la aplicación Tiempo de ejecución. El contenedor AOP genera en proxy en tiempo de ejecución. 7 SPRING FRAMEWORK 2.X
Soporte AOP en Spring Actualmente hay tres frameworks AOP: AspectJ(http://eclipse.org/aspectj) Jboss AOP(http://labs.jboss.com/portal/jbossaop/index.html) Spring AOP(http://www.springframework.org) El soporte de AOP con Spring tiene cuatro alternativas: Spring AOP basados en proxies en tiempo de ejecución(disponible en todas las versiones de Spring) Aspectos AspectJ dirigidos a anotaciones(sólo disponible en la versión 2.x de Spring) Aspectos POJO puros(sólo disponible en la versión 2.x de Spring) Aspectos AspectJ inyectados(disponible en todas las versiones de Spring) Los tres primeros sólo permiten intercepción a nivel de método. El cuarto permite inyección a nivel de constructor y atributo(raramente requeridos). 8 SPRING FRAMEWORK 2.X
Implementación AOP en Spring Los frameworks de AOP son diversos. Algunos presentan la funcionalidad de aplicar aspectos cuando se modifica el valor de un atributo, mientras que otros se quedan al nivel de invocación de métodos(soporte Spring). Nos centraremos en cómo Spring permite implementar AOP. Los advice de Spring están escritos en Java. Los pointcuts son definidos via XML dentro de la configuración de Spring. Spring aplica los aspectos en tiempo de ejecución. Genera el proxy cuando se carga el bean dentro del BeanFactory. No es necesario ningún compilador especial. 9 SPRING FRAMEWORK 2.X
Implementación AOP en Spring Generación de proxies: Si la clase target cumple un interfaz Spring usa la clase de la JDK java.lang.reflect.proxy. Si la clase target no cumple un interfaz se usa CGLIB (similar a Hibernate para las propiedades/asociaciones perezosas). Dinámicamente se genera una subclase del target introduciendo la lógica definida en el advice. La subclase a su vez delega la ejecución de los distintos métodos a la clase target. Limitaciones a CGLIB: No pueden aplicarse aspectos a métodos marcados como final. Spring genera una subclase de la clase target. Se recomienda el uso de java.lang.reflect.proxy mediante interfaz ya que favorece el desacoplo de la solución. Spring sólo soporta joinpoints a nivel de método. AspectJ y JBossAOP soportan joinpoints a nivel de constructor y atributo. 10 SPRING FRAMEWORK 2.X
11 SPRING FRAMEWORK 2.X Advice. Tipos
Poincut. Tipos Permiten definir dónde los advice son aplicados. Pointcuts determinan si un determinado método de una determinada clase cumple con un criterio particular. Spring permite que los advice sean tejidos dentro de las clases de la aplicación de una manera flexible. public interface Pointcut { public abstract ClassFilter getclassfilter(); public abstract MethodMatcher getmethodmatcher(); } 12 SPRING FRAMEWORK 2.X
Pointcut interfaces. ClassFilter y MethodMatcher public interface ClassFilter { public abstract boolean matches(class targetclass); } public interface MethodMatcher { public abstract boolean matches(method method, Class targetclass); public abstract boolean isruntime(); } public abstract boolean matches(method method, Class targetclass, Object args[]); 13 SPRING FRAMEWORK 2.X
Advisor Advice Pointcut Advisor 14 SPRING FRAMEWORK 2.X
Pointcut estáticos StaticMethodMatcherPointcut es la clase base para poder crear pointcuts estáticos. En el caso de necesitar implementar uno propio únicamente es necesario sobreescribir esta clase e implementar el método ismatch. Pointcut estáticos provistos por Spring: NameMatchMethodPointcut: Permite el uso de wildcard * public void setmappedname(string) public void setmappednames(string[]) Ej:set* Todoslosmétodossetter Pointcut con expresiones regulares(regexpmethodpointcut). Permite definir expresiones regulares de tipo Perl (concretamente las de Java) para definir los métodos que van a ser interceptados. 15 SPRING FRAMEWORK 2.X
Pointcut dinámicos ControlFlowPointcut: Recoge la información de la pila de llamada del thread actual. Ejemplo podríamos interceptar la llamada de un determinado servlet mediante un MethodBeforeAdvice. Este tipo de pointcut tiene asociada una penalización del rendimiento de la aplicación con respecto a otros pointcut dinámicos. Java1.4 cinco veces más lento. Java1.3 diez veces más lento. ControlFlowPointcut es el único pointcut dinámico provisto por Spring. Recordar que se pueden desarrollar pointcut dinámicos implementando el interfaz MethodMatcher devolviendo true en el método isruntime() del mencionado interfaz. 16 SPRING FRAMEWORK 2.X
Operaciones sobre pointcuts Spring permite la union y la intersección de pointcuts ComposablePointcut. Se pueden combinar cualquier número de pointcut, ClassFilter y MethodMatcher. 17 SPRING FRAMEWORK 2.X
Definiendo Pointcuts con AspectJ Aunque es posible aprovechar la riqueza de las expresiones regulares para definir el conjunto de puntos de ejecución de un determinados advice, AspectJ provee un lenguaje de definición de pointcut más fino. Para definir expresiones AspectJ para la definición de Pointcut es necesario usar la clase AspectJExpressionPointcut 18 SPRING FRAMEWORK 2.X
Introductions Introductions son advice que afectan en el ámbito de clase, permitiendo añadir métodos y atributos nuevos en la clase. Permite los mismos beneficios que la herencia múltiple. IntroductionMethodInterceptor es un subinterfaz de MethodInterceptor añadiendo un método adicional: boolean implementsinterface(class intf); Si el método implementsinterface devuelve true entonces IntroductionMethodInterceptor es responsable de implementar el mencionado interfaz. Cualquier invocación de un método declarado en el interfaz será delegado al método invoke() de IntroductionMethodInterceptor CUIDADO al llamar una clase con Introduction fuera de Spring!!! 19 SPRING FRAMEWORK 2.X
ProxyFactoryBean En el caso que se quiera aplicar el mismo advice a varios componentes, es posible definir un ProxyFactoryBean abstracto con el objeto de extender el mismo estableciendo el valor de la propiedad target. 20 SPRING FRAMEWORK 2.X
Autoproxying Cuando el número de objetos proxy es pequeño con ProxyFactoryBean es suficiente. En el caso de aumentar el tamaño de objetos proxy es necesario que el contenedor los cree de manera explícita, ya que la cantidad de configuración con ProxyFactoryBean es excesiva. Hay dos alternativas: Autoproxying basados en advisors declarados en el contexto de Spring. Autoproxying basados en aspectos con anotaciones AspectJ. Correspondientes al primer tipo tenemos las siguientes alternativas: BeanNameAutoProxyCreator: Mediante una expresión podemos identificar el conjunto de beans dentro de la factoría que se quiere interceptar con un determinado advice DefaultAdvisorAutoProxyCreator: Sólo trabaja con advisors (ya que necesita saber a qué beans debería aplicar el aspecto Consiste en un BeanPostProcessor que peina el contexto en la búsqueda de Advisor. 21 SPRING FRAMEWORK 2.X
22 SPRING FRAMEWORK 2.X BeanNameAutoProxyCreator
23 SPRING FRAMEWORK 2.X DefaultAdvisorAutoProxyCreator
Autoproxyingbasados en aspectos con anotaciones AspectJ SedefineelaspectocomounaclasePOJOnormal,lacualseanota. Sedefineunmétodovacíoalqueseleasocialaexpresiónquedefineelpointcut. Posteriormente con las anotaciones @Before, @After y @AfterThrowing se anotan los métodos llamados antes de la ejecución del método, después y en el caso de excepción, respectivamente. Es posible anotar una función con la anotación @Around a la cual se pasa un parámetro con información asociada al joinpoint que permite invocar el método original. Para que funcionen correctamente este tipo de aspectos es necesario crear el bean de la clase AnnotationAwareAspectJAutoProxyCreator Sin embargo, la configuración para este bean es muy farragosa, con lo que con Spring viene el elemento de configuración <aop:aspectj-autoproxy> que realiza toda la configuración de manera interna y transparente al desarrollador. Para ello es necesario definir el namespace aop en el fichero de configuración del contexto de Spring. <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> 24 SPRING FRAMEWORK 2.X
Declarando aspectos puramente POJOS En la version Spring 2.x el equipo de desarrollo ha decidido que la configuración de aspectos mediante ProxyFactoryBean necesitaba demasiada configuración. Anteriormente se ha definido un elemento del namespace aop (<aop:aspectj-autoproxy)). Dentro de este espacio de nombres aparecen los elementos definidos en la tabla. Enestecasonoesnecesarioanotarlaclasequeimplementaeladvice. Presenta la ventaja que cualquier clase puede convertirse en advice. 25 SPRING FRAMEWORK 2.X