Está en la página 1de 159

Introduccin al Framework Spring

Haga clic para modificar el estilo de subttulo del patrn

Qu es Spring?
Spring es un framework ligero para el desarrollo de aplicaciones. Strtus, WebWork y otros son frameworks para web. Spring, por contra, da soporte a todas las capas de una aplicacin. Nos evita la fontanera que normalmente el desarrollador se ve obligado a implementar a mano.

Historia de Spring
Publicado en 2002/2003 por Rod Johnson y Juergen Holler Empez siendo un ejemplo en el libro Expert One-on-One J2EE Design and Development de Rod Johnson. Spring 1.0 se publica en marzo del 2004 A partir de 2004/2005 Spring se populariza como framework de desarrollo para aplicaciones Java/J2EE

Spring & JEE?


Spring

no es un servidor de aplicaciones JEE, sino que se integra en las aplicaciones que se despliegan sobre ellos, y sobre aplicaciones Java en general. Spring sustituye elegantemente? algunos de los servicios que aportan los servidores de aplicaciones JEE.

Qu aporta Spring?
Spring

propone una estructura consistente para toda la aplicacin Facilita un mtodo consistente para pegar todos los elementos de la aplicacin. Abierto a la integracin con mltiples estndares e implementaciones populares como: Hibernate, JDO, TopLink, EJB, RMI, JNDI, JMS, Web Services, Struts, etc. Permite aumentar nuestra productividad evitndo al desarrollador la tarea de implementar tareas derivadas de la integracin de los componentes de la aplicacin.

Filosofa de Spring
From springframework.org

Los creadores de Spring defienden que: JEE debera ser ms sencilla de usar Es preferible programar interfaces a programar clases, pero sto conlleva usualmente un coste adicional de implementacin. Spring lo facilita reduciendo la implementacin desacoplada basndose en interfaces. La especificacin de JavaBeans ofrece ciertas ventajas a la hora de externalizar y modularizar la configuracin de las aplicaciones. El paradigma OO debe imponerse sobre la tecnologa subyacente como _JEE

Filosofa de Spring
Filosofa

POJO, menos interfaces y excepciones chequeadas que fuerzan a complicar el cdigo cuando integramos elementos diferentes. La prueba del software son esenciales. Spring nos ayuda a implementar cdigo chequeable mediante pruebas unitarias. La aplicacin de Spring debe ser placentera. El cdigo de la aplicacin no debe depender de las APIs de Spring. Spring no debe competir con soluciones que ya funcionan, sino permitir su fcil integracin en la aplicacin (Ej, Hibernate, JDO, etc.)

Arquitectura
from springframework.org

Tecnologa no invasiva
Qu implica esto? No fuerza a importar o extender ninguna API de Spring. Una tecnologa invasiva compromete nuestro cdigo con sus implementaciones Anti-patrones:

EJB nos fuerza a usar JNDI Struts 1.x fuerza a extender la clase Action

Los Frameworks invasivos son por lo general difciles de testear.

Estructura de Spring
Fundamentalmente, Spring se compone de: Contenedor de inversin de control (IoC)

Aplicacin de la tcnica de inyeccin de dependencias (Fowler)

Un

framework AOP. capa de abstraccin de servicios

Spring facilita un framework AOP basado en proxy. Integrable con AspectJ o AspectWerkz Integracin consistente con varios estndares y APIs populares.

Una

Todo ello est basado en la implementacin de aplicaciones usando POJOs.

Spring IoC Container


Inyeccin de dependencias
Haga clic para modificar el estilo de subttulo del patrn

Para qu vale?
Gestiona

objetos como componentes, permitiendo:


Crearlos Configurarlos Cablearlos (Wiring) Enlazado entre objetos. Controlar todo si ciclo de vida Controlar su destruccin

Ofrece

varios tipos de contenedor diferentes, clasificables en dos tipos:


BeanFactory ApplicationContext (ms completo)

Aplicaciones fuertemente acopladas


Descarguemos

cdigo. Funciona? Cmo estn las clases? Con cuantos tipos de actores puede funcionar el espectculo que estamos modelando? Qu tengo que hacer para variar el tipo de actor?

el piloto 1.0 y analicemos su

Refactorizando

Bajamos ahora el piloto 2.0. Qu hemos mejorado? Estn las clases completamente desacopladas por el mero hecho de utilizar una interfaz?

Taller prctico
Completar el modelo para que incorpore la clase es.uniovi.si.factoria.Factoria que: haga de factora sea un singleton tenga un mtodo Object getService(String) que cuando reciba Malabarista devuelva una instancia de la clase Malabarista. (Resuelto en piloto 3.0)

El contenedor BeanFactory
El

BeanFactory es una implementacin del patrn factora que permite crear beans declarndolos en un ficheros XML cuya raiz es la etiqueta <beans> El XML contiene uno o ms elementos de tipo <bean>

Atributo id (o nombre) para identificar el bean Atributo class que especifica el nombre cualificado completo de la clase que implementar el bean bautizado con id

El contenedor BeanFactory
defecto, los beans son tratados como singletons (Dessign patterns, GoF94), aunque existen otros posibles patrones de comportamiento. Ejemplo:
<beans> <bean id=widgetService
The beans ID The beans fullyqualified classname

Por

class=com.zabada.base.WidgetService > </bean> </beans>

El contenedor BeanFactory

Para utilizarlo: El documento XML debe ser encapsulado por alguna de las siguientes clases wrapper.

BeanFactory factory = new XmlBeanFactory(<documento xml>); Factory.getBean(<identificador del bean>);

Implementacin
ByteArrayResource ClassPathResource DescriptiveResource

FileSystemResource

Propsito El documento viene como un array de bytes Busca el documento en el classpath Mantiene una descripcin del documento pero no el fichero de recursos en s. Carga el documento del sistema

El contenedor BeanFactory
El

documento XML declara los beans, asocindoles el identificador por el cual van a ser referenciados.

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="actor" class="es.uniovi.si.Malabarista"/> </beans>

Taller prctico
Descargar

fuente. Extender sta versin del piloto para que la clase Show:

piloto 4.0 y examinar el cdigo

Implemente un interfaz evento que contenga su mtodo de comienzo. Sea tambin creada por medio de la factora BeanFactory, bajo el id de evento.

(Resuelto en piloto 5.0)

El ciclo de vida con BeanFactory

El ciclo de vida con BeanFactory Etapa Descripcin


Instantiate. Populate properties. Set Bean name Set Bean Factory Postprocess (antes de la inicializacin) Intialize beans PostProcess Bean Ready to Use Destroy Bean Instancia el Bean Spring Inyecta las propiedades. Si el bean implementa BeanNameAware, Spring le facilita su id invocando setBeanName. Si el bean implementa BeanFactoryAware, Spring le facilita su factora invocando setFactory. Si existen BeanPostProcessors, Spring invoca su mtodo postProcessBeforeInitialization() Si implementa InitializingBean, invoca afterPropertiesSet() Si existen BeanPostProcessors, Spring invoca su mtodo postProcessAfterInitialization() El bean pasa a estar disponible. Si implementa DisposableBean, se invoca su mtodo destroy()

Taller prctico
A

partir del piloto 5.0,

Definir un constructor pblico en la clase Malabarista que inicialice el nmero de objetos con los que hace los malabarismos. Modificar el bean.xml para que reciba 15 como parmetro de constructor al crear el bean. Probarlo Una vez comprobado, sobrecargamos el constructor con otro que reciba una cadena de texto y la muestre por pantalla. Qu sucede? Aadir la etiqueta type para forzar a que se dispare el constructor que nos interesa. (resuelto en piloto 6.0)

Inyeccin de parmetros por mtodos setter


Es

el segundo tipo de inyeccin de dependencias posible. En lugar de pasarle la informacin por medio del mtodo constructor, le decimos a Spring que le haga llegar la propiedad en el bean.xml Para ello debemos:

Tener un mtodo set para la propiedad Aadir una etiqueta property anidada a la definicin del bean en el bean.xml

<property name ="numeroObjetos" value="15"/>

Inyeccin de referencias de objetos


Adems

de valores sencillos, es posible inyectar una referencia a otro bean dado de alta en el contenedor. Ejemplo:
<bean name=widgetService class=com.zabada.base. WidgetServiceImpl> <property name=widgetDAO> <ref bean=myWidgetDAO/> </property> </bean>

Esto

implica que la clase WidgetServiceImpl deber tener un mtodo setWidgetDAO(WidgetServiceImpl ref)

Taller prctico
Modificar

el piloto para que la clase Show reciba como dependencia la instancia de la clases Malabarista en su propiedad actor. (Resuelto en piloto 7.0)

El Contenedor ApplicationContext
Es

l) Permite ms opciones:

una extensin del BeanFactory (hereda de

Incorpora mecanismos para la externalizacin de cadenas de texto e internacionalizacin (i18n) Unifica la carga de recursos, como las imgenes. Permite implementar un modelo de paso de mensajes mediante eventos a los beans, declarndolos como listeners del evento.

Por

lo general, se usa ste en lugar del BeanFactory, a no ser que estemos en entornos de recursos restringidos (dispositivos mviles o similares).

El Contenedor ApplicationContext
Hay

tres implementaciones del contenedor:


Tipo Descripcin Carga el documento XML buscndolo en el classpath

ClassPathXmlApplicationContext

FileSystemXmlApplicationContext

Lo busca en el sistema de ficheros Ejemplo: XmlWebApplicationContext = new Lo busca como doc. XML ApplicationContext context FileSystemXmlApplicationContext("c:/foo.xml"); contenido en una aplicacin web.

El ciclo de vida con ApplicationContext

Taller prctico
Descargar

la versin 8.0 del piloto y examinar el cdigo fuente. Ejecutarlo para comprobar que funciona correctamente.

Taller prctico Juntndolo todo


Vamos

a extender el piloto 8.0 de forma que:

Aparezca una interfaz Instrumento con el mtodo toca() que devuelve un String. Aparezca una clase Saxofon que implemente la interfaz Instrumento y suene tuuuut tuuuuu tutuuuu utuuuu Aparezca un nuevo actor de tipo Instrumentista tal que:
Reciba por setter:

Nombre El instrumento que toca

Al actuar, muestre un mensaje diciendo que fulanito hace con el sonido que haga el instrumento que est tocando

Damos de alta un nuevo bean kenny, que se

Problema

Supuesto:

Contratamos a otro saxofonista para el Show:

<bean id="kenny" class="com.springinaction.springidol.Instrumentalist"> <property name=nombre value=juan/> <property name="instrument"> <ref bean="saxofon"/> </property> </bean>

Pero:

A Kenny G (que ye muy fino) no le gusta compartir el saxofn Cuntas instancias se crean del instrumento?

Inner Beans
Inspirados

en las inner classes de Java (Clases que de definen dentro de otras clases) Los inner beans son beans que se definen dentro de otros beans, y cuyo mbito se reduce al bean contenedor. El bean contenido slo ser accesible por el que lo contiene:
<property name="instrument"> <bean class="org.springinaction.springidol.Saxophone" /> </property>

(Ver ejemplo en piloto 10.0)

Cableado de colecciones
Hasta

ahora hemos visto como utilizar Spring para configurar propiedades simples, de un solo valor o referencia. Pero Cmo hacerlo cuando tratamos con colecciones? Spring permite trabajar con cuatro tipos de colecciones.
Coleccin List Set Map Descripcin Lista de elementos con duplicados permitidos Conjunto (sin elementos repetidos) Coleccin de pares nombre-valor donde ambos elementos pueden ser de cualquier tipo

Cableado de colecciones
Si

quisiramos que en Show participasen kenny y el bean actor.


Modificaremos la clase Show para que:
En lugar de tener un atributo de tipo actor, lo tenga de tipo Collection<Actor>, con su correspondiente mtodo setActores() Al comenzar el show, haga actuar a todos los actores del espectculo que encuentre en la coleccin.
for ( Actor actor:actores ){ actor.actua(); }

Extendemos el beans.xml para anidar a los dos actores


<property name="actores"> <list> <ref bean/>

Taller prctico: Repasando


A

partir del piloto 10, completarlo para que entre el malabarista y el saxofonista, acte un hombre orquesta que toque el saxofn, la armnica y la guitarra. La armnica es suya y no la comparte, pero la guitarra es de la organizacin del show. Usaremos por convenio los nombres:

Clase Guitarra. Clase Armonica Clase HombreOrquesta Clase Hombre orquesta: Benja

Cableado de Mapas
Para

cablear un Map,

El objeto se tiene que esperar que le pasen como parmetro una instancia de la clase Map.

Public void setInstrumentos(Map <String,Instrumento>)

El beans.xml debe enlazar el mapa con el parmetro instrumentos.

<map> <entry key="la guitarra" value-ref="fender" />

Taller prctico
piloto 11.0 para que en lugar de pasar directamente las referencias a los beans que toca el Hombre Orquesta, le pasemos un mapa con el nombre que le queramos dar al instrumento, de forma que el mensaje al tocarlo sea El hombre orquesta toca la guitarra: rrriaaannn riiiaaaannn riiiiaaaannnnnnnn Resuelto en piloto 12
Extender

Taller prctico
Modificar

el piloto 12 para que:

A cada actor pueda asignrsele un nombre artstico cada vez que se enlace al show La salida una vez resuelto, ser algo como: Presentamos a Tony Malabares Haciendo malabarismos con 15 objetos Presentamos a El Increible hombre orquesta El hombre orquesta toca la guitarra:rrriaaannn riiiaaaannn riiiiaaaannnnnnnn El hombre orquesta toca la armnica:tui tui tuiiiiii tuiiiiiii Presentamos a Kenny G! Kenny G hace ttuuuuuu tuuuu tuuuuut

Auto-Cableado en Spring (Autowire)


Hemos

visto como cablear beans

Con el elemento <constructor-arg> Con el elemento <property>

Problema:

En una aplicacin complicada, esta prctica puede degenerar en un XML desmesurado e inmanejable. Alternativa: En lugar de definir explcitamente las relaciones entre beans, podemos dejar que Spring decida como debe cablearlos, mediante la propiedad autowire del elemento <bean>

Auto-Cableado en Spring (Autowire)


Tipos

de autocableado:
Descripcin Trata de buscar un bean declarado en el contenedor cuyo nombre o identificadorcoincida con la propiedad del bean marcado como autocableable Busca un nico bean que coincida en tipo con la propiedad del bean marcado como autocableable. Si no se encuentra, la propiedad se queda sin mapear. Si se encuentra ms de una, salta una excepcin
UnsatisfiedDependencyException

Tipo byName

byType

constructo Trata de encajar uno o ms beans r declarados en el contenedor con los

Autowire byName
Todo

en Spring tiene un nombre.

<bean id="kenny" class="es.uniovi.si.Instrumentista"> <property name="nombre" value="Kenny G"/> <property name="instrumento"> <bean class="es.uniovi.si.Saxofon"/> </property> </bean>

Si

queremos simplificar el XML:

<bean id=instrumento class="es.uniovi.si.Saxofon"/>

<bean id="kenny" class="es.uniovi.si.Instrumentista autowire=byName> <property name="nombre" value="Kenny G"/> </bean>

Lo

cambiamos y lo probamos. Funciona? (Resuelto en piloto 14.0)

Autowire byType
Similar

a byName, salvo que la bsqueda la realiza por tipo, y no por nombre Por cada bean autocableado por tipo,

Introspecciona las propiedades del bean Por cada setXXX no cableado explcitamente en el beans.xml, busca un bean declarado que coincida en tipo con la propiedad, y si lo encuentra, lo cablea.

Probamos:

Partiendo del piloto 14.0, cambiar el autowire a byType. Funciona? Qu podemos hacer para arreglarlo? (Resuelto en piloto 15.0)

Autowire por constructor


til

cuando utilizamos inyeccin de dependencias en el constructor. Si declaramos un bean autocableable por constructor:

Spring busca por instrospeccin los constructores del bean Por cada uno, trata de buscar candidatos para satisfacer los tipos de sus parmetros entre los beans declarados en el beans.xml Si los encuentra, invoca el constructor.

En

caso de ambigedad, dispara una excepcin igual que cuando usamos byType

Autodeteccin de autowire
Nos

permite delegar en el contenedor la decisin de qu bean debe ser cableado con otro, y de qu forma.

<bean id="duke" class="com.springinaction.springidol.PoeticJuggler" autowire="autodetect" />

Para

este ejemplo, Spring tratar de autocablear el bean por constructor, y en caso de no tener xito, lo intentar por tipo.

Autocableado por defecto


Si

vamos a adoptar una poltica comn de autocableado para todos los beans, podemos declararla a nivel de contenedor:

<beans default-autowire="byName"> </beans>

Esta

propiedad se puede sobrescribir a nivel de bean individual.

Control del ciclo de vida del Bean


Hasta

ahora hemos usado la creacin bsica de beans, asumiendo que Spring crea una nica instancia de cada uno. Existen ms opciones para gestionar la instanciacin de beans:

Control del nmero de instancias creadas


Singleton Una por request Una por peticin

Creacin mediante factora Incializacin y destruccin controlada del bean

Control del ciclo de vida del Bean


Problema:

Control del mbito (scope) del Por defecto, todos son singleton bean
en determinados contextos, no podemos/queremos usar singletons. Utilizando el atributo scope del elemento bean determinamos su ciclo de vida:
Descripcin Valor por defecto. nica instancia por contenedor ? Se crea una instancia por peticin El mbito se reduce a la request HTTP (Spring MVC) El mbito se reduce a la sesin HTTP

Scope singleton prototype request session

Uso del atributo scope


Si

queremos definir un bean como prototype:

<bean id=<identificador> class=<nombre de la clase> scope={prototype |singleton |request |session |global-session/>

Taller prctico
Modificar

la versin 15 del piloto para que:

El bean instrumento se instancie una vez por cada bean que lo utilice El Hombre Orquesta lo aada a su coleccin de instrumentos Junto con el sonido del saxofn, se muestre el valor de la referencia del objeto que lo identifica unvocamente en la JVM. Si ahora quitamos el scope Hay diferencia?

(Resuelto en piloto 16.0)

Creacin de beans desde factoras


Normalmente

creamos las clases con su constructor pblico, pero por distintos motivos (cdigo heredad, libreras de terceras partes, etc.), es posible que el bean que queremos cablear deba ser creado a partir de un factory method Ejemplo:

Queremos incorporar a modelo del Show un escenario que tenemos ya implementado de otra parte del sistema. Como es nico, viene implementado como singlenton.

Creacin de beans desde factoras


Para

la instanciacin de este tipo de objetos, el elemento bean permite especificar el factory-method que debe invocar el contenedor para obtener una instancia del bean.

<bean id=<identificador>" class=<nombre de la clase>" factory-method=<mtodo que retorna la instancia>" />

Taller prctico
A

partir del piloto 16.0:


Crear una clase Escenario que implemente el patrn singleton, y llamamos al mtodo de creacin de instancia getInstancia(). Sobrescribir su mtodo toString para que retorne Escenario Central. Modificar la aplicacin para que el Show, antes de comenzar la actuacin, obtenga una referencia al escenario y muestre por pantalla:

Bienvenidos al Escenario Central

(Resuelto en trabajo 17.0)

Inicializacin y destruccin de beans


Es

posible que un determinado bean requiera hacer operaciones de inicializacin antes de poder realizar su tarea, o bien liberar recursos conexiones a bbdd, cierre ficheros, etc- antes de su destruccin. Los atributos:
init-method destroy-method nos permiten decirle al contenedor qu dos mtodos queremos que realicen estas tareas de inicializacin y destruccin.

Al igual que con autowire, se pueden especificar los nombres de los mtodos constructor y destructor a

Taller prctico
A

partir de trabajo 17.0:


Implementar en el saxofn y en la armnica un mtodo afinar y otro limpiar que publiquen sendos mensajes por la consola. Hacer que ambos se disparen como mtodo de inicializacin y mtodo de destruccin. Probarlo. Funciona? Y si ahora lo pongo por defecto para todos los beans?

<beans default-init-method="afinar" default-destroy-method="limpiar">

Taller prctico
Modificar

y extender la clase Escenario para que tenga los mtidos


abrirTelon cerrarTelon

Que

impriman sendos mensajes y que sea invocado al inicializar y al destruir la clase.

Inicializacin por I.D. por interfaces


A

partir del ejemplo anterior una vez terminado, probar a forzar a que la clase Instrumentista implemente las interfaces

InitializingBean DisposableBean Qu ocurre? Hacer lo necesario para que sea compilable y ejecutarlo. Resuelto en piloto 18.0

Taller prctico
Modificar

la clase Escenario de nuevo para que la inicializacin y destruccin se realicen ahora por usando los dos interfaces:

InitializingBean DisposableBean

Cableado avanzado de beans


Haga clic para modificar el estilo de subttulo del patrn

Herencia
Hasta

ahora hemos declarado los beans de forma individual, estableciendo las propiedades de cada uno una a una de forma especfica. Problema: Puede degenerar en ficheros de configuracin muy extensos y poco tratables. Ejemplo:

Tenemos muchos beans de un determinado tipo que comparten caractersticas ->Tenemos que definir la misma caracterstica en todos ellos. En una orquesta, todos los instrumentistas tocan la misma cancin

Herencia
Al

igual que en la POO, es posible definir relaciones padre-hijo entre los beans declarados en un contenedor. Un bean que extiende la declaracin de otro bean se define como sub-bean del segundo. Dos atributos especficos para esto:

Parent: Declara de qu bean hereda el que estamos declarando Abstract: Declara el bean como abstracto, y por lo tanto, no instanciable.

Ejemplo
<bean id=<nombre padre>" class=<clase del padre>" abstract="true"> <property name=<propiedad comn>" ref=<ref bean a heredar>"/> </bean> <bean id=<hombre hijo 1>" parent=<nombre padre>"> <property name=<otra propiedad>" value=<valor 1>"/> </bean> <bean id=<hombre hijo 2>" parent=<nombre padre>"> <property name=<otra propiedad>" value=<valor 2>"/> </bean>

Taller prctico
Modificar

para que:

el piloto a partir de su versin 18

Aparezca un bean Saxofonista que:


Sea abstracto Est ligado al Saxofn

En el show participe un nuevo saxofonista con id=bill y nombre=Bill Clinton. Ser presentado como El presidente Clinton!.

Resuelto en trabajo 19.0

Taller prctico - repaso


Extender

ahora el piloto 19.0 para que:

Tanto los instrumentistas como los hombres orquesta tengan un atributo de tipo String que se llame tema. Poner a todos los implicados de acuerdo para que toquen Paquito el Chocolatero

... Se repite configuracin? Debemos ligar el atributo tema a la clase Actor? Y el malabarista? Creamos una nueva clase intermedia?

Abstraccin de propiedades comunes


En

determinados contextos, puede que necesitemos compartir valores de propiedades entre beans de diferentes clases. Spring permite hacer esto declarando un bean abstracto sin especificar su clase, y forzando a los hijos a que lo extiendan.
<bean id=<bean base>" abstract="true"> <property name=<nombre propiedad compartida>" value=<valor de la propriedad>" /> </bean>

Taller prctico
Definir

un bean abstracto Interprete que defina el valor de la propierdad tema para que toque Paquito el chocolatero y configurar los bean Hombre Orquesta y Saxofonista para que hereden dicha propiedad del intrprete. (Resuelto en piloto 20.0)

Inyeccin de mtodos
Habitual

el lenguajes dinmicos como Ruby. Consiste en aadir nuevos mtodos a una clase ya compilada, o modificar la definicin de alguno ya existente. En Java y otros LOO clsicos no se puede hacer esto, son poco flexibles Spring permite simular la inyeccin de mtodos en los beans que tenga declarados en el contenedor. Dos tipos:

Remplazo de mtodos Inyeccin de Getter

Remplazo bsico de mtodo


interceptar las invocaciones que se realicen al mtodo sustituido para inyectar en medio la nueva implementacin del mismo Es necesario implementar un objeto que cumpla la interfaz MethodReplacer
public class <Nombre Clase> implements MethodReplacer { public Object reimplement(Object target, Method method, Object[] args) throws Throwable { ... }

Spring

Remplazo bsico de mtodo


Una

vez dado de alta, sustituimos el mtodo en el beans.xml

<bean id="<bean sustituto>" class=<clase method replacer>"/> <bean ...> ... <replaced-method name=<mtodo a sustituir> replacer=<bean sustituto>"/> </bean>

Taller prctico
Descargar

piloto 20.0 (importante partir de ste, incluye nuevas referencias a jars) y extenderlo para sustituir el sonido del saxofn. Para ello:

Implementar una clase Sintentizador que modifique el sonido del saxofn, retornando una nueva cadena de sonido. Darlo de alta en el beans.xml como sintentizador y utilizar el elemento replacedmethod en el beans instrumento para sobrescribir el mtodo toca. Funciona? Qu clase est realmente ejecutndose? Aadir a la nueva cadena de sonido la referencia al objeto que se ejectura

Inyeccin de Getter
Si

el mtodo que queremos inyectar es un mtodo getter para que retorne un bean contenido en el contenedor, podemos directamente obviar su implementacin y decirle a Spring que intercepte la peticin.

<bean id=<nombre bean> class=<clase del bean>> <lookup-method name=<nombre getter>" bean=<bean a retornar>"/> </bean>

Taller prctico
Vamos

a darle el cambiazo a kenny, sustituyndole el saxofn por la guitarra fender. Para ello,
Modificamos el mtodo actua de la clase Instrumentista para que cuando acceda al instrumento lo haga a travs de su mtodo getter. Transformamos el inner bean fender en uno normal para que pueda ser accedido desde otros beans. Sobrescribimos el getter de kenny para que getInstrumento retorne el bean fender. (Resuelto en piloto 21.0)

Qu clase est realmente implementando el mtodo

Registrando editores de propiedades personalizados Las propiedades vistas hasta ahora son

simples, pero normalmente nos enfrentamos a estructuras ms complejas Ej: Reconocer y procesar una URL:
http://www.xmethods.net/sd/BabelFishService.wsdl

Spring,

puede convertir automticamente el texto anterior en un objeto de tipo URL. Cmo lo hace? Mediante un property editor basado en la especificacin de Java Beans.

El interfaz PropertyEditor
Interfaz

java.beans.PropertyEditor Permite especificar como se deben mapear datos de tipo String en tipos no String. Fuerza a tener dos mtodos:

getAsText()- Devuelve la representacin en forma de String del valor setAsText(String) Transforma el String que recibe en el formato correspondiente.

Si

se trata de dar un valor de tipo String a una propiedad que no lo es, se disparar el mtodo setAsText() para realizar la conversin. getAsText() se usar para representar el

PropertyEditors de Spring
Spring

incorpora varios editores de propiedades a medida, basados en la clase PropertyEditorSupport.

PropertyEditor ClassEditor

Utilidad Transforma un String en una propiedad de tipo java.lang.Class. CustomDateEditor Transforma de String a java.util.Date FileEditor LocaleEditor Transforma de String a java.io.File Transforma de String a java.util.Locales StringArrayProperty De una lista de Strings con comas a Editor un array de Strings

Desarrollo de PropertyEditors a medida


Podemos

desarrollar nuestro propio editor de propiedades personalizado para nuestra aplicacin. Ejemplo (A partir de piloto 22.00): Vamos a aadir informacin de contacto a todos los instrumentistas. Creamos una clase Telefono con los atributos

codigoPais numero extension

sus correspondientes getters y constructor parametrizado.

Desarrollo de PropertyEditors a medida


una instancia de la clase Telefono como propiedad de la clase Instrumentista Y ahora configuraremos el contenedor para asignarle un telfono a Kenny G. <bean id="telefono1" class="es.uniovi.si.Telefono"> <constructor-arg value="0034"/> <constructor-arg value="985105094"/> <constructor-arg value="00"/> </bean>
<bean id="kenny" parent="Saxofonista"> <property name="nombre" value="Kenny
Aadimos

Desarrollo de PropertyEditors a medida

Alternativa:

Creamos nuestro propio PropertyEditor:

public class TelefonoPropertyEditor extends PropertyEditorSupport {

Desarrollo de PropertyEditors a medida


Ahora slo nos falta decirle a Spring cuando y como aplicar el nuevo property editor, por medio del CustomEditorConfigurer CustomEditorConfigurer es un BeanPostProcessor que carga los editores de propiedades en la BeanFactory. Para ello:

<bean class="org.springframework.beans.factory

Desarrollo de PropertyEditors a medida

Ahora ya podemos asignrselo directamente a kenny

<bean id="kenny" parent="Saxofonista"> <property name="nombre" value="Kenny G" /> <property name="telefono" value="0034-650423932-00" /> <lookup-method name="getInstrumento" bean="fender" /> </bean>

(Resuelto en piloto 23.0)

Taller prctico
Creamos

email:

ahora un propertyEditor para el

email.setUsuario(texto.substring(0,texto.indexOf('@'))); email.setServidor(texto.substring( texto.indexOf('@')+1,texto.length()));

Creamos una clase email con dos propiedades: usuario y servidor. Hacemos sus accessors y su constructor parametrizado Aadimos Email como propiedad de instrumentista Creamos el properyeditor para convertir el email

Aadimos el nuevo email property editor al map del CustomEditorConfigurer

Los beans especiales de Spring


La

mayora de los beans que manejar el contenedor son tratados de la misma forma la vista hasta ahora. Para determinadas tareas, Spring permite especificar que determinados beans sean tratados de manera especial. Para marcar aquellos beans que deben ser tratados como tales, nos serviremos de la inyeccin de dependencias por interfaces.

Los beans especiales de Spring


Mediante

estos, podemos:

Tomar parte en la creacin de los beans y en el ciclo de vida de la factora mediante posprocesamiento. Cargar ficheros de configuracin externos en ficheros property Cargar mensajes de texto, como base para la internacionalizacin. Ligar el bean a la recepcin de eventos.

Beans de posprocesamiento
Permiten

programar ciertas tareas que se dispararn antes y despus de la inicializacin de los beans del contenedor El bean de PostProcesamiento se configura POR CONTENEDOR Para esto, tenemos que:

Crear un bean que implemente la interfaz BeanPostProcessor Darlo de alta en el contenedor.

Creacin del BeanPostProcessor


El

bean debe implementar la interfaz BeanPostProcessor:

public interface BeanPostProcessor { Object postProcessBeforeInitialization( Object bean, String name) throws BeansException; Object postProcessAfterInitialization( Object bean, String name) throws BeansException; }

Configurar el postprocesador
Tenemos

dos alternativas:

Si trabajamos con BeanFactory: Si trabajamos con ApplicationContext:

BeanPostProcessor fuddifier = new Fuddifier(); factory.addBeanPostProcessor(fuddifier);

<bean class=<nombre de la clase postprocesadora>"/>

En el segundo caso, basta con esto. El propio contenedor se dar cuenta de que el bean instanciado implementa la interfaz BeanPostProcessor y lo incluir como tal en el ciclo de vida de los beans corrientes.

Ejemplo: Con hacienda hemos topado


Queremos

desarrollar un postprocesador que se chive de quienes estn actuando en el Show, de forma que para todo aquel bean que tenga nombre (y por lo tanto, mtodo getNombre()), se genere un mensaje por pantalla notificando que fulanito ha actuado. Para ello, habr que

desarrollar el postprocesador darlo de alta en el contenedor

HaciendaPostProcessor

public class HaciendaPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitia lization(Object bean,

HaciendaPostProcessor
Y

lo damos de alta en el contenedor Resuelto en Piloto 24.0

<bean class="es.uniovi.si.HaciendaPostProcessor"/>

Taller prctico
Descargar

el piloto 24.0 Importarlo en Eclipse Examinar el cdigo fuente

Taller prctico: De mal en peor


Ahora

llega la SGAE! Extender el piloto par aadir un nuevo bean postprocesador SGAEPostProcessor que saque por pantalla todos aquellos temas que se toquen en el Show, intentando acceder al mtodo getTema de cada bean declarado en el mismo. (Ser necesario aadir el mtodo getTema() a los que ya cuentan con setTema()) (Resuelto en piloto 25.0).

Postprocesamiento de la factora
Similar

al BeanPostProcessor, el BeanFactoryPostProcessor permite realizar tareas de postprocesamiento sobre todo el contenedor de Spring.

public interface BeanFactoryPostProcessor { void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory) throws BeansException; }


El

mtodo postProcessBeanFactory es invocado por Spring una vez las definiciones hayan sido cargadas, pero antes de que los beans sean instanciados.

Postprocesamiento de la factora
Ejemplo:

Para saber cuantos beans han sido declarados en el beans.xml

public class BeanCounter implements BeanFactoryPostProcessor { private Logger LOGGER = Logger.getLogger(BeanCounter.class); public void postProcessBeanFactory( ConfigurableListableBeanFactory factory) throws BeansException { LOGGER.debug("BEAN COUNT: " + factory.getBeanDefinitionCount()); } }

Para

darlo de alta en el contenedor.

<bean id="beanCounterclass="com.spring.BeanCounter"/>

Externalizando la configuracin de los beans


Es

posible configurar los beans mediante el beans.xml y el elemento <property>. Sin embargo, no conviene mezclar el cableado de beans con la configuracin especfica de nuestra aplicacin. Spring proporciona el objeto PropertyPlaceholderConfigurer si trabajamos con el ApplicationContext para esto.
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceh olderConfigurer"> <property name="location" value=<fichero.properties>" />

Externalizando la configuracin de los beans


Puede

que necesitemos modular la configuracin en diferentes ficheros de propiedades:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceh olderConfigurer"> <property name="locations"> <list> <value>jdbc.properties</value> <value>security.properties</value> <value>application.properties</value> </list> </bean>

Externalizando la configuracin de los beans


Ahora

podemos recuperar los valores de configuracin referencindolos por medio de variables en lugar de tenerlos hardcodeados en el beans.xml

<bean id="dataSource class= "org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url value="${database.url}" /> <property name="driverClassName value="${database.driver}" /> <property name="username value="${database.user}" /> <property name="password value="${database.password}" /> </bean>

Externalizando la configuracin de los beans

Taller prctico
Extender

el piloto 25.0 para que tome los siguientes datos del fichero Configuracion.properties:

numero.malabares=25 tema=19 das y 500 noches (Resuelto en piloto 26.0)

Beans atentos (Aware)


En

determinados casos, los beans necesitarn tener acceso a objetos de Spring, como el ApplicationContext. Esto se resuelve mediante inyeccin de dependencias por interfaz. Hay tres posibles interfaces que dan acceso a sendos objetos:

BeanNameAware BeanFactoryAware ApplicationContextAware

Quin Soy?: BeanNameAware


Implementando

la interfaz BeanNameAware le estoy diciendo al contenedor que queremos que nos inyecte el identificador con el que el bean ha sido declarado en el beans.xml
public interface BeanNameAware { void setBeanName(String name); }

Cuando

cada bean sea cagado, el contenedor comprobar por introspeccin si implementa esta interfaz ( isInstanceOf()). En tal caso, invocar su mtodo setBeanName() pasndole como parmetro el identificador del bean.

De dnde vengo?:

BeanFactoryAware & ApplicationContextAware De la misma forma, accedemos a la factora y al contexto:


public class StudentServiceImpl implements StudentService, ApplicationContextAware { private ApplicationContext context; public void setApplicationContext(ApplicationContext context) { this.context = context; } }

Taller prctico
Modificar

el piloto 26.0 par que:

La clase Malabarista reciba y almacene


Contexto La factora Su nombre

Forzar adems a que cuando reciba su nombre, muestre un mensaje diciendo: Hola, me llamo actor

(Resuelto en piloto 27.0)

Gestin de Eventos en Spring


La

inyeccin de dependencias no es la nica forma de interaccin entre beans en Spring. La otra alternativa es basarse en el modelo de eventos de los JavaBeans. Un bean publicador dispara un evento que ser recibido por todos aquellos que estn registrados como escuchadores. El publicado y los escuchadores (listeners) no se conocen entre s, estn desacoplados.

Gestin de Eventos en Spring


Es

Spring un bean puede ser

Publisher Listener Ambos dos.

Creacin de eventos
Un

evento para poder ser gestionado por Spring debe extender la clase ApplicationEvent.

public class CourseFullEvent extends ApplicationEvent { private Course course; public CourseFullEvent(Object source, Course course) { super(source); this.course = course; } public Course getCourse() { return course; } }

Publicacin de Eventos
Una

vez creado Cmo lo publicamos? El objeto ApplicationContext tiene el mtodo publishEvent(), que nos permite publicar instancias de la clase ApplicationEvent. Todo aquel bean ApplicationListener registrado en el contenedor recibir el evento mediante una llamada a su mtodo onApplicationEvent()
ApplicationContext context = ; Course course = ; context.publishEvent(new CourseFullEvent(this, course));

Problema: Necesitamos hacer que un bean sea capa de procesar eventos.

Ser Listener
Para

que un bean dado de alta en el contenedor reciba eventos que extiendan la clase ApplicationEvent, deber implementar la Interfaz ApplicationListener

Public interface ApplicationListener { public void onApplicationEvent(ApplicationEvent event); }

El

contenedor detecta que es listener de los eventos y lo aade automticamente a la suscripcin.

Taller prctico
Extender

el piloto 27 para que:

Aparezca una clase Representante y un bean de su tipo declarado en el contendor. Aparezca un evento PaseEvent con un mtodo getActor() que retorne la instancia de Actor que acta en el Show. El bean Show lance un evento PaseEvent por cada actor que acte para que el Representante lo escuche y tome nota de cuanto debe facturar al gestor. (Resuelto en el piloto 28.0)

Taller prctico
El

show va a ser retransmitido por televisin, y por lo tanto, es necesario avisar al tcnico de control para que cuando termine una actuacin importante, pase a publicidad, y cuando comience la siguiente importante, retome la conexin con el escenario. La tele slo se interesa por las grandes personalidades como Kenny G y Bill Clinton, pero para mantener al pblico viendo los anuncios, los ponemos al comienzo y fin de espectculo. Para modelar esto, vamos a necesitar crear dos tipos de eventos diferentes que

Taller prctico
Tendremos

que:

Creamos dos nuevos eventos:


ComienzoVIPEvent con una propiedad Actor FinVIPEvent

Modificar la clase Show para que cuando comiencen bill o kenny se dispare el correspondiente evento, as como cuando finalicen. Implementar TecnicoTelevision y dar de alta al bean urdazi como tal. Tiene que ser capaz de escuchar eventos de tipo ApplicationEvent, y publicar los mensajes de inicio y fin de la retransmisin, dependiendo del evento que le llegue. Resuelto en piloto 28.5

Spring AOP
Programacin modificar a estilo de Haga clic para Orientada el Aspectos subttulo del patrn

Definicin de POA
Fue presentada en pblico por Gregor Kickzales y su equipo de investigacin de Palo Alto Research Center en 1996. Paradigma de programacin relativamente reciente. De esta forma se consigue:

Razonar mejor sobre los conceptos. Eliminar la dispersin del cdigo. Implementaciones resultan ms comprensibles, adaptables y reusables.

Definicin de Aspecto
Un aspecto es una unidad modular que se disemina por la estructura de otras unidades funcionales. Los aspectos existen tanto en la etapa de diseo como en la de implementacin. Un aspecto de diseo es una unidad modular del diseo que se entremezcla en la estructura de otras partes del diseo. Un aspecto de programa o de cdigo es una unidad modular del programa que aparece en otras unidades modulares del programa (G. Kiczales)

Definicin de Aspecto
Los aspectos son la unidad bsica de la POA, y pueden definirse como las partes de una aplicacin que describen las cuestiones claves relacionadas con la semntica esencial o el rendimiento. Tambin pueden verse como los elementos que se diseminan por todo el cdigo y que son difciles de describir localmente con respecto a otros componentes. Ej.: patrones de acceso a memoria, sincronizacin de procesos concurrentes, manejo de errores, etc.

Estructura de un Programa OA

Estructura de un Programa OA
Se

muestra un programa como un todo formado por un conjunto de aspectos ms un modelo de objetos. Con el modelo de objetos se objetos se recoge la funcionalidad de negocio. Los aspectos recogen caractersticas de rendimiento, infraestructura y otras no relacionadas con el modelo de negocio.

Objetivos Fundamentales de la POA


Extraer

y centralizar en un solo punto los "crosscutting concepts cada decisin se toma en un lugar concreto y no diseminada por la aplicacin. Minimizar las dependencias entre ellos desacoplar los distintos elementos que intervienen en un programa.

Objetivos Fundamentales de la POA

Idea principal es centralizar en un solo punto todos los aspectos comunes a las clases que forman el sistema software.

Figura 1. Evolucin de un sistema OO a uno OA

Ventajas de la POA
Un

cdigo menos enmaraado, ms natural y ms reducido. facilidad para razonar sobre los conceptos, ya que estn separados y las dependencias entre ellos son mnimas. cdigo ms fcil de depurar y ms fcil de mantener.

Mayor

Un

Ventajas de la POA
Se

consigue que un conjunto grande de modificaciones en la definicin de una materia tenga un impacto mnimo en las otras. tiene un cdigo ms reusable y que se puede acoplar y desacoplar cuando sea necesario.

Se

Programa Tradicional Vs. OA

Conceptos Bsicos de POA


Punto de enlace Una posicin bien definida dentro del cdigo orientado (Join Point) a objetos, por ejemplo, la declaracin de un mtodo.

Aspect o

Punto de corte Un conjunto de condiciones aplicadas a un punto de (Pointcut) enlace que, al cumplirse, activarn el punto de corte y se ejecutar el punto de ejecucin asignado a dicho punto de corte. Punto de ejecucin Fragmento de cdigo que se ejecuta cuando se activa o consejo (Advice) un punto de corte.

Otros Conceptos de POA

Objetivo (target) Proxy

El objetivo o target es el objeto sobre el que se va a aplicar el aspecto, (Advised object), el objeto aconsejado. Es el objeto resultante tras aplicar el Advice al objeto objetivo. Desde el punto de vista del cliente, el objeto objetivo (preAOP) y el objeto Proxy (postAOP) son el mismo (transparente) Tejido de aspectos: Proceso por el cual se mezcla el cdigo del modelo OO con los aspectos involucrados en su ejecucin

Weaving

Consideraciones Importantes
POA no rompe con las tcnicas de programacin orientadas a objetos sino que las complementa y extiende. El nuevo paradigma de la programacin orientada a aspectos es soportado por los llamados lenguajes de aspectos, que proporcionan constructores para capturar los elementos que se diseminan por todo el sistema.
La

Fundamentos de la POA
Para tener un programa orientado a aspectos necesitamos definir los siguientes elementos:

Un lenguaje para definir la funcionalidad bsica. Este lenguaje se conoce como lenguaje base. Suele ser un lenguaje de propsito general, tal como C++, C# o Java. En general, se podran utilizar tambin lenguajes no imperativos. Uno o varios lenguajes de aspectos. El lenguaje de aspectos define la forma de los aspectos, por ejemplo, los aspectos de AspectJ se programan de forma muy parecida a las clases. Un tejedor de aspectos.

Fundamentos de la POA
Los puntos de enlace son una clase especial de interfaz entre los aspectos y los mdulos del lenguaje de componentes. Son los lugares del cdigo en los que ste se puede aumentar con comportamientos adicionales. Estos comportamientos se especifican en los aspectos.

Fundamentos de la POA
El

encargado de realizar este proceso de mezcla se conoce como tejedor (del trmino ingls weaver). Se encarga de mezclar los diferentes mecanismos de abstraccin y composicin que aparecen en los lenguajes de aspectos y componentes ayudndose de los puntos de enlace. El proceso de mezcla se puede retrasar para hacerse en tiempo de ejecucin, o hacerse en tiempo de compilacin.

Implementacin en Lenguajes

Estructura de una implementacin en los lenguajes tradicionales.

Implementacin en lenguajes

Estructura de una implementacin en los lenguajes de aspectos.

Tipos de enlazado (Weaving)


Los

aspectos son tejidos en los objetos objetivo en los puntos de enlazado especificados (joinpoints). Puede ser en tres momentos de la vida del objeto:

Tiempo de compilacin El cdigo fuente del objetivo es enriquecido con el cdigo de los aspectos en los joinpoints, y luego compilado. As trabaja AspectJ Durante la carga de clases Los aspectos se enlazan en el momento de la carga de clases. Se requiere un ClassLoader especial. En tiempo de ejecucin Aplicando el patrn Proxy, se intercepta la peticin y se delega en los

Qu nos permite Spring AOP?


Soporte de Spring

Los advices en Spring estn escritos en Java


Podemos usar IDEs corrientes Conocemos el lenguaje

Los

pointcuts se declaran en un fichero XML

Estndar conocido. AspectJ requiere una sintaxis especial.

Spring

realiza el tejido de aspectos en tiempo de ejecucin, sirvindose del patrn Proxy.

Funcionamiento de Spring AOP


La

ejecucin el objeto acosejado por el aspecto es interceptada por un objeto Proxy que realiza las labores definidas en el pointcut. Los proxies sern creados por el ApplicationContext cuando carga los beans declarados en el contenedor. Dado que se crean en tiempo de ejecucin, no se necesita ningn compilador especfico para AOP con Spring.

Tipos de intercepcin
Dos

tipos:

La clase aspectizada implementa un interfaz que contiene los mtodos por los que se van a realizar los pointcuts
Spring usa la java.lang.reflect.Proxy para generar automticamente una nueva clase que implementa la ineterfaz, teje los aspectos e intercepta toda llamada a esos mtodos de la interfaz.

La clase es un POJO. Spring usa CGLIB para generar un proxy a medida en tiempo de compilacin, extendiendo la clase objetivo (por lo que no podemos usar mtodos final.)

AOP Alliance Interfaces


Spring

implementa las interfaces de AOP Alliance:


Acuerdo para promover un uso estandarizado de la AOP independientemente de la tecnologa (Java) subyacente sobre la que se generen los aspectos. Un aspecto creado con estos interfaces es portable a otras plataformas AOP

Puntos de unin en Spring


Spring

slo soporta Method Joinpoints Otras plataformas (AspectJ, Aspect JBOSS) soportan field joinpoints, lo que permite aspectos ms refinados. No obstante, si todos los accesos a atributos se realizan por medio de los mtodos accessor, se pueden emular los efectos.

Tipos de advices
Tipo Around Interface org.aopalliance.intercept.MethodInterceptor Descripcin Intercepta las llamadas al mtodo Se invoca antes de que el mtodo sea invocado Se invoca tras al mtodo Se invoca cuando el objetivo dispara una excepcin.

Before

org.springframework.aop.BeforeAdvice

After Trhows

org.springframework.aop.AfterReturningAdvice org.springframework.aop.ThrowsAdvice

Mi primer aspecto
Vamos a probar los aspectos extendiendo el Espectculo que ya tenemos funcionando, haciendo que aparezca un nuevo actor: el pblico. Antes de nada, bajamos de la zona de descargas el jar de la CGLIB y lo aadimos en lib y al classpath del proyecto actual. Creamos una clase Audiencia con los siguientes mtodos, y la declaramos como el bean audiencia en el beans.xml: Mtodo Muestra el mensaje tomenAsiento() El pblico se sienta apagueMoviles() El pblico apaga sus mviles

aplaudan()

CLAP CLAP CLAP CLAP!!!!! BRAVO!!!!!

Mi primer aspecto
Ahora...

Quin invoca a la clase audiencia? El pblico no va dirigido ni por el actor de turno, ni por el propio espectculo, sino que responden a situaciones automticamente. Vamos a crear un aspecto para que dispare los mtodos del bean audiencia antes y despus de cada actuacin de un actor.

Implementando el aspecto
Creamos

una nueva clase Java es.uniovi.si.aop.AudienciaAdvice, de forma que:

Implemente:
AfterReturningAdvice MethodBeforeAdvice ThrowsAdvice

Tenga una propiedad audiencia para poder obtener una referencia a la misma por inyeccin. Implementamos los tres mtodos, invocando a los mtodos de audiencia que corresponda en cada contexto.

Implementando el aspecto
Una

vez creada la clase AudiencieAdvise, damos de alta el bean audiencieAdvice inyectando la audiencia como propiedad. Ahora tenemos que definir el punto de corte. Con el punto de corte le diremos a Spring donde exactamente queremos aplicar el advice que hemos implementado. Spring permite utilizar varios tipos de puntos de corte.

Declarando un punto de corte con expresiones regulares. Objetivo: seleccionar los mtodos sobre los

que aplicar el advise. Solucin: Aplicacin de un patrn de expresiones regulares sobre la signatura de los mtodos Spring incorpora dos clases que implementan estos puntos de corte:

org.springframework.aop.support.Perl5RegexpMet hodPointcut (Requiere Jakarta ORO) org.springframework.aop.support.JdkRegexpMeth odPointcut (Usa el RegExp incorporado en Java 1.4)

Declarando un punto de corte con expresiones regulares. Para utilizar el punto de corte, primero

tenemos que declararlo como bean en el contenedor:

<bean id=actuacionPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut"> <property name="pattern" value=".*actua" /> </bean>

Este

patrn encaja con cualquier mtodo que se llame actua.

Asociando pointcut y advice


Ahora

tenemos que asociar el punto de corte con el advice:

<bean id="audienciaAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="audienciaAdvice" /> <property name="pointcut" ref="actuacionPointcut" /> </bean>

Con

esto ya tenemos el aspecto completo implementado. Para que funcione, nos falta un ltimo paso, la creacin de los objetos proxy de los beans que queremos aspectizar

Creacin de los Proxies


Para

todo bean aconsejado por un advisor, es necesario crear un proxy. El proxy es el que realmente actuar cuando el advisor haga su trabajo, y por lo tanto, es el que realmente debemos cablear. Para crear un proxy para el kenny, por ejemplo:

Creacin del proxy para los beans aspectizados


<bean id="kenny" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="kennyTarget" /> <property name="interceptorNames" value="audienciaAdvisor" /> <property name="proxyInterfaces value="es.uniovi.si.Actor" /> </bean> <bean id="kennyTarget" parent="Saxofonista"> <property name="nombre" value="Kenny G" /> <property name="telefono" value="0034-650423942-00" /> <lookup-method name="getInstrumento" bean="fender" /> </bean>

Creamos

los proxies para el resto de los actores y ya podemos ejecutar la aplicacin. (Resuelto en Piltoto 29.0)

Taller prctico
Modificar

el piloto 29.0 para que la guitarra dispare irremisiblemente una excepcin de tipo Runtime() y comprobar que el pblico pide su devolucin. (Resuelto en piloto 30.0)

Taller prctico El vigilante de seguridad


La

organizacin del espectculo est preocupada por los controles de inmigracin que la seguridad social est realizando sin previo aviso, as que decide poner un vigilante que, antes de cada actuacin, le pida las credenciales a los artistas para dejarles trabajar o no. Tendremos que seguir los siguientes pasos...

Taller prctico El vigilante de seguridad


Aadir

a Actor un mtodo getCredenciales que retorne un boolean (indicando si las tiene o no). Creamos es.uniovi.si.VigilanteAdvise para que implemente BeforeAdvise, y lo damos de alta como vigilanteAdvise. Implementamos el mtodo before para que muestre un mensaje indicando si el target (tercer parmetro del mtodo) tiene o no credenciales. El punto de corte... Ya lo tenemos declarado! Ser el mismo que para el ejemplo anterior Asociamos el nuevo advisor con el punto de

Taller prctico Probando al vigilante


A

partir del piloto 31.0, modificarlo para que:


el malabarista no tenga credenciales El vigilante lance una excepcin de tipo InmigranteIlegalExcepcion avisando de que no puede trabajar. Ejecutarlo

Qu

ha ocurrido? Dnde deberamos capturar la excepcin para que la aplicacin siga funcionando? Capturarla en el lugar adecuado y mostrar un mensaje de la organizacin explicando la cancelacin de la actuacin. (Resuelto en piloto 32.0)

Ponindolo en prctica
Haga clic para modificar el estilo de subttulo del patrn

Aplicando Spring
Vamos

a comenzar la implementacin de una infraestructura base basada en Spring para el desarrollo de aplicaciones. Desarrollaremos el esqueleto de una aplicacin modelo sirvindonos de Spring para ahorrarnos cdigo que solemos tener que implementar para cada aplicacin.

Primer paso: Preparando el entorno


Partir

del ltimo piloto manipulado y:

Eliminar todas las clases menos la factora Dejar el beans.xml sin ningn bean para poder empezar de cero.

Vamos

a partir de un entorno vaco sobre el cual trabajar. Implementar la clase Main con mtodo main y mtodo comienzo. El main obtendr una referencia a s mismo por medio de la factora e invocar su mtodo comienzo.

Desarrollando el men
Queremos

desarrollar un men configurable que valga para cualquier aplicacin de ventanas. Cada elemento del men (MenuItem) contendr una descripcin (description) y uno o varios subelementos, que sern inyectados por Spring. Configurarlo para que de momento tenga la siguiente estructura:

Desarrollo del men

Finalmente, implementar un mtodo printMenu en la clase Main que pinte tabuladamente las diferentes opciones del men invocando el toString() de muniItem. (Resuelto en piloto 40.0)

Inyectando lgica en el men


Vamos

ello:

a aplicar el patrn command. Para

Implementaremos un interface es.uniovi.si.menu.MenuCommand que contenga un mtodo execute. Prepararemos el MenuItem para que:
Pueda recibir uno o varios Command por inyeccin, y los invoque en orden de inyeccin en un mtodo run

Creamos un comando (ejemplo, es.uniovi.si.comandos.AbrirCommand) para cada opcin final del men que de momento slo mostrar un mensaje cuando se invoque, y los inyectamos en su correspondiente opcin del men. (Resuelto piloto 41.0)

Activando y desactivando mens


Aadir a MenuItem una propuedad boolean active SIN INICIALIZAR, y modificarlo para que si vale false, el nombre del men aparezca entre * al llamar al toString(). Ej: *Abrir* Crear los eventos:

es.uniovi.si.menu.event.AuthorizeMenuItemsEvent es.uniovi.si.menu.event.DenyMenuItemsEvent es.uniovi.si.menu.event.AuthorizeAllMenuItemsEvent es.uniovi.si.menu.event.DenyAllMenuItemsEvent

de forma que los dos primeros contengan una coleccin con los ids (tal y como han sido asignados en el beans.xml) de los mens a activar o desactivar. Crear una clase MenuController, que implemente los mtodos

autorizeMenuItems() denyMenuItems() authorizeAll() denyAll()

de forma que se sirva de los eventos para activar o desactivar las opciones del men que le soliciten cambiar. Las dos primeras podrn recibir uno o varios ids de tipo String. Lo instanciamos como el bean menuController y se lo inyectamos a Main

Activando y desactivando mens

Configurar el men para que por defecto, todos los mens estn activos (uno a uno?), y cambiar lo necesario para que el men pegar aparezca desactivado. Para probarlo, modificar el mtodo comienzo de Main para que:
Pinte el men Desactive el men de cortar Pinte el men Active todas las opciones Pinte el men

(Resuelto en piloto 42.0)

Refactorizando
A estas alturas, decidimos que el no tiene sentido que Main contenga directamente el men ni que implemente el mtodo printMenu(). Refactorizamos la aplicacin para que sea el MenController el que contenga ambos elementos, de forma que el Main slo interacte con el menController. (Resuelto en piloto 43.0)

Servicio de Log
Aadir

un servicio de log tal que:

La interfaz de acceso sea es.uniovi.si.infraestructura.log.Log y tenga los mtodos:


log warn error fatalError

La clase que lo implemente sea es.uniovi.si.infraestructura.log.MiLog La clase Main tenga acceso al log y muestre un mensaje para corroborar que funciona.

Aspectizando el log

Implementamos el LogAdvice para que:

Al entrar trace un mensaje notificando que se ha invocado el mtodo X de la clase Y con los argumentos Z Al salir muestre un mensaje notificando el final del mtodo X de la clase Y retornando Z Al capturar una excepcin notifique un error.

Creamos la interfaz MenuItemInterface, dado que para interceptar las invocaciones el advice requiere un interfaz (que luego implementar el Proxy). Ahora el MenuItem contendr elementos de tipo MenuItemInterface (lo hace solo eclipse!) Creamos el pointcut para que capture invocaciones a los mtodos run de los mens Modificar el printMenu para que invoque cada mtodo run. Aspectizamos menuAbrir y probamos. (Resuelto en piloto 44.0)

Aspecto de seguridad

Implementamos ahora un aspecto materializado en es.uniovi.si.infraestructura.security.Securit yAdvice de forma que:


Reciba un objeto de tipo User en un atributo usuario con un mtodo getUser que retorne el id del usuario. Reciba un String[] con los usuarios autorizados a ejecutar la aplicacin Prepararlo para que antes de la invocacin del mtodo interceptado compruebe que el usuario tiene permisos para usar la aplicacin Se dispare antes de cada comando del men

La clase Main inicializar el bean User antes de invocar la impresin del men.
(Resuelto en trabajo 45.0)

También podría gustarte