Documentos de Académico
Documentos de Profesional
Documentos de Cultura
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
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
Estructura de Spring
Fundamentalmente, Spring se compone de: Contenedor de inversin de control (IoC)
Un
Spring facilita un framework AOP basado en proxy. Integrable con AspectJ o AspectWerkz Integracin consistente con varios estndares y APIs populares.
Una
Para qu vale?
Gestiona
Ofrece
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?
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
El contenedor BeanFactory
Para utilizarlo: El documento XML debe ser encapsulado por alguna de las siguientes clases wrapper.
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:
Implemente un interfaz evento que contenga su mtodo de comienzo. Sea tambin creada por medio de la factora BeanFactory, bajo el id de evento.
Taller prctico
A
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)
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
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
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:
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
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.
Taller prctico
Descargar
la versin 8.0 del piloto y examinar el cdigo fuente. Ejecutarlo para comprobar que funciona correctamente.
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:
Al actuar, muestre un mensaje diciendo que fulanito hace con el sonido que haga el instrumento que est tocando
Problema
Supuesto:
<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>
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
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.
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
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
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>
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
Autowire byName
Todo
<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
Lo
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)
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.
Para
este ejemplo, Spring tratar de autocablear el bean por constructor, y en caso de no tener xito, lo intentar por tipo.
vamos a adoptar una poltica comn de autocableado para todos los beans, podemos declararla a nivel de contenedor:
Esta
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 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
Taller prctico
Modificar
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?
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.
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.
Taller prctico
A
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
Taller prctico
Modificar
Que
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
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:
En el show participe un nuevo saxofonista con id=bill y nombre=Bill Clinton. Ser presentado como El presidente Clinton!.
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?
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:
Spring
<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)
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
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
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
Alternativa:
<bean class="org.springframework.beans.factory
<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>
Taller prctico
Creamos
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
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.
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:
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:
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.
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
HaciendaPostProcessor
public class HaciendaPostProcessor implements BeanPostProcessor { @Override public Object postProcessAfterInitia lization(Object bean,
HaciendaPostProcessor
Y
<bean class="es.uniovi.si.HaciendaPostProcessor"/>
Taller prctico
Descargar
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.
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:
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
<bean id="beanCounterclass="com.spring.BeanCounter"/>
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 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>
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>
Taller prctico
Extender
el piloto 25.0 para que tome los siguientes datos del fichero Configuracion.properties:
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:
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?:
Taller prctico
Modificar
Forzar adems a que cuando reciba su nombre, muestre un mensaje diciendo: Hola, me llamo actor
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.
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));
Ser Listener
Para
que un bean dado de alta en el contenedor reciba eventos que extiendan la clase ApplicationEvent, deber implementar la Interfaz ApplicationListener
El
Taller prctico
Extender
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:
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.
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.
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
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.
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
Implementacin en lenguajes
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
Los
Spring
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.)
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()
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
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
Este
<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
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:
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)
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...
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
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.
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:
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)
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:
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
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
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
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
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
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)