Sie sind auf Seite 1von 159

Spring es un framework ligero para el

desarrollo de aplicaciones.
Struts, 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.
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 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.
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.
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 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.)
from springframework.org
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.
Fundamentalmente, Spring se compone de:
Contenedor de inversin de control (IoC)
Aplicacin de la tcnica de inyeccin de dependencias
(Fowler)
Un framework AOP.
Spring facilita un framework AOP basado en proxy.
Integrable con AspectJ o AspectWerkz
Una capa de abstraccin de servicios
Integracin consistente con varios estndares y APIs
populares.

Todo ello est basado en la implementacin de


aplicaciones usando POJOs.
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)
Descarguemos el piloto 1.0 y analicemos su
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?
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 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
Por defecto, los beans son tratados como
singletons (Dessign patterns, GoF94),
aunque existen otros posibles patrones de
comportamiento.
Ejemplo:
The beans fully-
The beans ID qualified classname
<beans>
<bean id=widgetService
class=com.zabada.base.WidgetService>
</bean>
</beans>
Para utilizarlo:
BeanFactory factory = new XmlBeanFactory(<documento xml>);
Factory.getBean(<identificador del bean>);
El documento XML debe ser encapsulado por alguna de las
siguientes clases wrapper.
Implementacin Propsito
ByteArrayResource El documento viene como un array de bytes
ClassPathResource Busca el documento en el classpath
DescriptiveResource Mantiene una descripcin del documento
pero no el fichero de recursos en s.
FileSystemResource Carga el documento del sistema de ficheros
InputStreamResource Carga el documento como un inputStream
PortletContextResource Lo busca en el contexto de portlets
ServletContextResource Lo busca en el contexto de los servlets
UrlResource Lo descarga de una url concreta
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>
Descargar piloto 4.0 y examinar el cdigo
fuente.
Extender sta versin del piloto para que la
clase Show:
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)
Etapa Descripcin
Instantiate. Instancia el Bean
Populate properties. Spring Inyecta las propiedades.
Set Bean name Si el bean implementa BeanNameAware, Spring le
facilita su id invocando setBeanName.
Set Bean Factory Si el bean implementa BeanFactoryAware, Spring
le facilita su factora invocando setFactory.
Postprocess (antes de la Si existen BeanPostProcessors, Spring invoca su
inicializacin) mtodo postProcessBeforeInitialization()
Intialize beans Si implementa InitializingBean, invoca
afterPropertiesSet()
PostProcess Si existen BeanPostProcessors, Spring invoca su
mtodo postProcessAfterInitialization()
Bean Ready to Use El bean pasa a estar disponible.
Destroy Bean Si implementa DisposableBean, se invoca su
mtodo destroy()
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)
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"/>
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)
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)


Es una extensin del BeanFactory (hereda de l)
Permite ms opciones:
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).
Hay tres implementaciones del contenedor:
Tipo Descripcin
ClassPathXmlApplicationContext Carga el documento XML
buscndolo en el classpath
FileSystemXmlApplicationContext Lo busca en el sistema de ficheros
XmlWebApplicationContext Lo busca como doc. XML contenido
en una aplicacin web.

Ejemplo:
ApplicationContext context = new
FileSystemXmlApplicationContext("c:/foo.xml");
Descargar la versin 8.0 del piloto y examinar
el cdigo fuente.
Ejecutarlo para comprobar que funciona
correctamente.
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 llame Kenny
G , que toque el saxofn y hacemos que sea l el que
acte en el Show.
Resuelto en piloto 9.0
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?
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)
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 Descripcin
List Lista de elementos con duplicados permitidos
Set Conjunto (sin elementos repetidos)
Map Coleccin de pares nombre-valor donde ambos
elementos pueden ser de cualquier tipo
Props Coleccin de pares nombre-valor donde ambos
elementos son de tipo String
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/>

</list>
Resuelto en piloto 11.0
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

(Resuelto en piloto 11.0)


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" />

Extender 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
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 utuuuuuuuu
Resuelto en piloto 13
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>
Tipos de autocableado:
Tipo Descripcin
byName Trata de buscar un bean declarado en el contenedor cuyo
nombre o identificador- coincida con la propiedad del
bean marcado como autocableable
byType 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
constructor Trata de encajar uno o ms beans declarados en el
contenedor con los parmetros de alguno de los
constructores del bean.
autodetect Trata de aplicar el autowire por constructor, y en caso de
no poder, aplica byType. En caso de ambiegedad, salta
una excepcin.
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)
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)
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
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.
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.
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
Por defecto, todos son singleton
Problema: en determinados contextos, no
podemos/queremos usar singletons.
Utilizando el atributo scope del elemento
bean determinamos su ciclo de vida:

Scope Descripcin
singleton Valor por defecto. nica instancia por contenedor ?
prototype Se crea una instancia por peticin
request El mbito se reduce a la request HTTP (Spring MVC)
session El mbito se reduce a la sesin HTTP (Spring MVC)
global-session El mbito se reduce al contexto HTTP (Portlets)
Si queremos definir un bean como prototype:

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


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.
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>" />
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)


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 nivel
de contenedor con default-init-method y default-
destroy-method.
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">
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.
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


Modificar la clase Escenario de nuevo para
que la inicializacin y destruccin se realicen
ahora por usando los dos interfaces:
InitializingBean
DisposableBean
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
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.
<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>
Modificar el piloto a partir de su versin 18
para que:
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


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?
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>
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)
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
Spring 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 {
...
}
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>
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 replaced-method 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 (Wrapper).
Resuelto en Versin 21.0
(Ojo!!! Slo funciona si obtenemos el objeto a travs de
Spring!
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>
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
acta?
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.
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 valor.
Spring incorpora varios editores de
propiedades a medida, basados en la clase
PropertyEditorSupport.
PropertyEditor Utilidad
ClassEditor Transforma un String en una propiedad de tipo
java.lang.Class.
CustomDateEditor Transforma de String a java.util.Date
FileEditor Transforma de String a java.io.File
LocaleEditor Transforma de String a java.util.Locales
StringArrayPropertyEditor De una lista de Strings con comas a un array de
Strings
StringTrimmerEditor Hacer trim sobre el String.
URLEditor Transforma de String a URL
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
Y sus correspondientes getters y constructor
parametrizado.
Aadimos 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 G"/>
<property name="telefono" ref="telefono1"/>
<lookup-method name="getInstrumento" bean="fender"/>
</bean>
Funciona? S, pero es tedioso y poco prctico
Alternativa: Creamos nuestro propio
PropertyEditor:
public class TelefonoPropertyEditor extends PropertyEditorSupport {
public void setAsText(String texto){
String stripped = stripNonNumeric(texto);
String codigoPais = stripped.substring(0,3);
String numero = stripped.substring(3,12);
String extension = stripped.substring(12);
Telefono telefono = new Telefono(codigoPais, numero, extension);
setValue(telefono);}

private String stripNonNumeric(String original) {


StringBuffer allNumeric = new StringBuffer();
for(int i=0; i<original.length(); i++) {
char c = original.charAt(i);
if(Character.isDigit(c)) {
allNumeric.append(c);
}
}
return allNumeric.toString();}
}
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.config.CustomEditorConfigure
r">
<property name="customEditors">
<map>
<entry key="es.uniovi.si.Telefono">
<bean id="TelefonoEditor"
class="es.uniovi.si.TelefonoPropertyEditor">
</bean>
</entry>
</map>
</property>
</bean>
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)
Creamos ahora un propertyEditor para el email:
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
email.setUsuario(texto.substring(0,texto.indexOf('@')));
email.setServidor(texto.substring(
texto.indexOf('@')+1,texto.length()));
Aadimos el nuevo email property editor al map del
CustomEditorConfigurer
Le asignamos bill.clinton@whitehouse.org al bean bill.
Resuelto en 23.5
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.
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.
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.
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;
}
Tenemos dos alternativas:
Si trabajamos con BeanFactory:
BeanPostProcessor fuddifier = new Fuddifier();
factory.addBeanPostProcessor(fuddifier);
Si trabajamos con ApplicationContext:
<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.
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
public class HaciendaPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String arg1)
throws BeansException {
try {
Method method= bean.getClass().getMethod("getNombre");
if ( method!=null ){
String nombre = (String) method.invoke(bean,
null);
System.out.println("\t\tREGISTRADA ACTUACIN DE
"+nombre);
}
}
catch (NoSuchMethodException e) {
//No hacemos nada.
} catch (Exception ee) {
ee.printStackTrace();
}
return bean;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String arg1)
throws BeansException {
return bean;
}
}
Y lo damos de alta en el contenedor
<bean class="es.uniovi.si.HaciendaPostProcessor"/>

Resuelto en Piloto 24.0


Taller prctico
Descargar el piloto 24.0
Importarlo en Eclipse
Examinar el cdigo fuente
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).
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.
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"/>
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>" />
</bean>
Puede que necesitemos modular la
configuracin en diferentes ficheros de
propiedades:

<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPl
aceholderConfigurer">
<property name="locations">
<list>
<value>jdbc.properties</value>
<value>security.properties</value>
<value>application.properties</value>
</list>
</bean>
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>
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)


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
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 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;
}

}
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)
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.
Es Spring un bean puede ser
Publisher
Listener
Ambos dos.
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;
}
}
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.
Cmo se hace eso?
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.
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)
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 representen el comienzo y
el final de una actuacin. En el primero adems
enviaremos el actor participa en el mismo.
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
Programacin Orientada a Aspectos
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.
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)
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.
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.
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.
Idea principal es centralizar en un solo punto
todos los aspectos comunes a las clases que
forman el sistema software.
Clases
Clase A Clase B
Clase A Clase B
Comportamiento Comportamiento
propio propio Comportamiento Comportamiento
propio propio

Persistencia

Traza
Persistencia Traza
..
Aspectos

Figura 1. Evolucin de un sistema OO a uno OA


Un cdigo menos enmaraado, ms natural y
ms reducido.

Mayor facilidad para razonar sobre los


conceptos, ya que estn separados y las
dependencias entre ellos son mnimas.

Un cdigo ms fcil de depurar y ms fcil de


mantener.
Se consigue que un conjunto grande de
modificaciones en la definicin de una
materia tenga un impacto mnimo en las
otras.

Se tiene un cdigo ms reusable y que se


puede acoplar y desacoplar cuando sea
necesario.
Punto de enlace Una posicin bien definida dentro del cdigo
(Join Point) orientado a objetos, por ejemplo, la declaracin de
Aspecto

un mtodo.
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 Fragmento de cdigo que se ejecuta cuando se
ejecucin o activa un punto de corte.
consejo (Advice)
Objetivo (target) El objetivo o target es el objeto sobre el que se va a aplicar
el aspecto, (Advised object), el objeto aconsejado.

Proxy 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)
Weaving Tejido de aspectos: Proceso por el cual se mezcla el cdigo
del modelo OO con los aspectos involucrados en su
ejecucin
La 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.
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.
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.
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.
Estructura de una implementacin en
los lenguajes tradicionales.
Estructura de una implementacin
en los lenguajes de aspectos.
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 aspectos cuando
se requiere. Spring AOP trabaja de esta forma.
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.
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.
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.)
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
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.
Tipo Interface Descripcin
Around org.aopalliance.intercept.MethodInterceptor Intercepta las
llamadas al
mtodo
Before org.springframework.aop.BeforeAdvice Se invoca antes de
que el mtodo sea
invocado
After org.springframework.aop.AfterReturningAdvice Se invoca tras al
mtodo
Trhows org.springframework.aop.ThrowsAdvice Se invoca cuando
el objetivo dispara
una excepcin.
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!!!!!
pedirDevolucion() BOOOOO!!!!!! Queremos nuestro dinero!!!!!!
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.
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.
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.
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.Perl5RegexpMeth
odPointcut (Requiere Jakarta ORO)
org.springframework.aop.support.JdkRegexpMetho
dPointcut (Usa el RegExp incorporado en Java 1.4)
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.
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
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:
<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)
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)
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...
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 corte
mediante el pointcutadvisor vigilanteAdvisor.
Finalmente, en el proxy, forzamos a que tenga en cuenta
ambos interceptores:
<property name="interceptorNames"
value="audienciaAdvisor,vigilanteAdvisor" />
Resuelto en piloto 31.0
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)
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.
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.
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:
Archivo Edicin Acerca de

Abrir Cortar

Pegar

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)
Vamos a aplicar el patrn command. Para ello:
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)
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
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)
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)
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.
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)
Implementamos ahora un aspecto materializado en
es.uniovi.si.infraestructura.security.SecurityAdvice 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)

Das könnte Ihnen auch gefallen