Académique Documents
Professionnel Documents
Culture Documents
habis ledo esta frase muchas veces. Probablemente cada framework basado en Java proclama esta
misma idea. Entonces, Por qu Spring es diferente? Qu hace que sea especial y diferente al resto?
Para empezar (y esta es una de las opciones qu ms valoro) Spring se acopla a tu aplicacin sin
obligarte a modificar tu cdigo para utilizar las funcionalidades y beneficios que ofrece. Para usar
Spring no es imprescindible implementar un interfaz propio de Spring o heredar de una clase propia
(puede que para utilizar cierta funcionalidad avanzada s sea necesario, pero para un uso habitual
no); lo que significa que Spring estar ah pero tus clases sern Java puro y duro. Como mucho, tus
clases tendrn anotaciones propias de Spring, pero no dejan de ser anotaciones por lo que tu clase
ser reutilizable en cualquier momento, sin cambios. Esta caracterstica con otros frameworks es
impensable, ya que para poder utilizar dicho framework habrs tenido que implementar un interfaz
propio del framework y a la vez implementar los mtodos establecidos en dicho interfaz; mtodos
que fuera de ese framework no tienen ningn sentido ni utilidad (no hace falta que mencione
ninguno en concreto verdad?). Por tanto, aqui tenemos la primera ventaja: Gracias a Spring,
nuestro cdigo Java puede ser ms limpio, elegante y reutilizable. Elegante y reutilizable ya que la
filosofa de Spring nos gua a programar orientado a interfaces, de modo que toda nuestra
aplicacin sea altamente modular y posea bajo acoplamiento. Veamos cmo en la Segunda ventaja
(Antes de empezar he de avisaros que esta entrada no pretende ser una charla tcnica, es ms, est
orientada a ser divulgativa y a mostrar lo que podemos hacer con Spring sin entrar en detalles de
cmo hacerlo por no hablar de que es un peln extensa :P )
public Elfo(){
arma = new Arco();
}
@Override
public void ataca() {
arma.dispara();
}
}
Como vis en el ejemplo, Elfo crea su propia instancia de Arma, un Arco. Esto provoca que las
instancias de Elfo estn fuertemente acopladas a la clase Arco, lo que obviamente fuerza a que un
Elfo slo pueda utilizar un Arco como arma. Qu ocurre si queremos darle una espada?
Este fuerte acoplamiento nos lleva a otro problema. Qu ocurre si queremos aplicar test unitarios
al mtodo ataca()? No tenemos ninguna forma de probar diferentes implementaciones (o stubs o
mocks) de la clase Arma, ya que un Elfo utiliza directamente una instancia de clase Arco
Aqu es donde entra en juego el concepto Inyeccin de Dependencias: Los objetos reciben sus
dependencias en tiempo de creacin, de manera que ellos no son responsables de la instanciacin e
inicializacin de esas dependencias. Por eso se dice que las dependencias se inyectan en el objeto
que las necesite, porque de esta forma, el objeto no debe preocuparse de crear esas instancias.
Veamos el mismo ejemplo, pero ahora con inyeccin de dependencias:
@Override
public void ataca() {
arma.dispara();
}
}
Como vis, an pareciendo lo mismo, el panorama cambia ampliamente. En esta ocasin, las
instancias de Elfo no crean una instancia de Arma, por tanto podrn utilizar cualquier arma que se
les asigne desde el constructor, ya que todas las armas deben implementar el interfaz Arma. Aqu
se aprecia nuevamente la ventaja de programar orientado a Interfaces (os suena
polimorfismo?? :P). Este tipo de inyeccin de dependencias se conoce con el nombre de: Inyeccin
por constructor.
Lo ms importante es que la clase Elfo, no est acoplada a ninguna implementacin concreta del
interfaz Arma, por tanto no importa que arma utilice siempre y cuando ese arma implemente el
interfaz Arma. Si un objeto slo conoce a sus dependencias mediante su interfaz (no por
su implementacin), podremos cambiar la implementacin de esa dependencia como
consideremos necesario sin que el objeto sea consciente de esos cambios y, por tanto,
sin que le afecten.
Pero, y si en mitad de una batalla queremos cambiar el arma de nuestro guerrero? Aqui entra en
juego el segundo tipo de inyeccin de dependencias: Inyeccin por setter.
SoC (Separation of Concerns) y DRY (Dont repeat yourself) nos ayudarn a crear e implementar
clases y mtodos que sigan el patrn 1:1, es decir, Una determinada funcionalidad debe estar
implementada en un slo sitio de nuestra aplicacin y slo debe llevar a cabo esa funcionalidad.
Por ejemplo, qu ocurrira en nuestra clase Elfo si quisiramos que cada vez que un elfo ataque, se
escriba una traza indicando qu elfo ha atacado?
Podramos hacer lo siguiente:
Obviamente si seguimos por ese camino, vamos a llegar inevitablemente a un muy mal diseo de
nuestro cdigo, que desembocar en dos sntomas inequvocos de que necesitamos aplicar SoC y
DRY (y por ende AOP):
1.
2.
Scattering (dispersin del cdigo): Una determinada funcionalidad est dispersa por
mltiples clases y/o mtodos lo que implica que cualquier tarea de refactorizacin de cdigo se
va a hacer muy tediosa y originar fallos y errores que no tenemos contemplados (si la
aplicacin es muuuy grande y el cdigo est muy enmaraado y disperso, quizs no
conozcamos los efectos secundarios que puede tener un determinado cambio en el cdigo)
Aqu es donde Spring aplica su magia de AOP de una manera muy elegante; nosotros simplemente
tenemos que decirle a Spring lo siguiente: Tras la ejecucin del mtodo ataca() del interfaz
Guerrero, ejecutame el mtodo loggingAtaque() de la clase Logging.
La clase Logging ser una clase que nosotros habremos creado y que se encargar nicamente de
realizar trazas de log de diversos mtodos de nuestra aplicacin. No es mucho ms legible y
elegante nuestro cdigo ahora? Y fijos ni siquiera hemos tenido que modificar la clase Elfo, o la
clase Enano porque obviamente ese horrible System.out.println() que habamos escrito
anteriormente ya no sera necesario.
Un ejemplo ms claro en el que se demuestra que utilizar AOP con Spring es una gozada, es el
ejemplo de la seguridad. Retomemos nuestro mtodo encargado de listar los clientes almacenados
en la base de datos, tiene sentido hacer esto?:
Es decir, cada vez que queramos que un mtodo acceda a la base de datos, el mtodo debe
encargarse de controlar si el usuario tiene permisos?? Nuevamente, queda mucho ms elegante
hacer algo del estilo a lo siguiente:
Oye Spring, mira: Antes de ejecutar el mtodo listClientes() de la clase ClienteDAO,
ejecuta el mtodo tienePermisos(usuarioEnSession) de la clase Seguridad.
De esta forma nuestro cdigo de listClientes() quedara:
escribir unas 20 lneas de cdigo 15 de las cuales sern siempre iguales. Pero no slo pasa esto con
JDBC, tenemos este mismo comportamiento si utilizamos REST o JMS en Java.
En este caso Spring elimina este cdigo boilerplate mediante el uso de Templates o Plantillas de
Cdigo. De esta forma, en Spring existen plantillas para JDBC, JNDI, JMS, REST, . todas las API
que tengan cdigo susceptible de ser repetitivo, tendrn su correspondiente plantilla en Spring.
En el caso de JDBC, tenemos la plantilla JdbcTemplate, que se encargar de encapsular todo el
cdigo repetitivo de las conexiones a base de datos, para que nosotros nos centremos en lo que
realmente nos interesa: La query y los resultados que obtenemos. De esta forma le diremos a
Spring: Mira, ejectame esta query y los resultados (en caso de que haya alguno) me los mapeas a
este objeto mediante este mtodo. Pero esto es para el caso en el que los resultados que devuelve
nuestra query estn compuestos por cierto nmero de filas y columnas, si el resultado es mucho ms
simple, todo se simplifica, por ejemplo:
int
num_clientes
=
JdbcTemplate(datasource).queryForInt("select
clientes");
count(*)
new
from
Como vis las plantillas en Spring nos permitirn que nuestro cdigo sea mucho ms limpio y
elegante, a la vez que evitamos tener que procesar todas esas Excepciones de tipo SQLException,
que por otra parte nunca he sabido muy bien qu hacer con ellas Si en algn momento de la
ejecucin de tu cdigo se lanza una SQLException Cmo se supone que debe actuar nuestro
cdigo?? Es decir, son excepciones no recuperablesuna vez que salta una, no podemos hacer
mucho: DUPLICATE PRIMARY KEY . no tenemos muchas opciones, como mucho avisar al
usuario con un mensaje de error pero poco ms. entonces mi pregunta es: Por qu estamos
obligados a capturarlas? Por qu no son unchecked exceptions? . Pero bueno, ese ya es otro
tema (Por cierto, Spring tambin ha pensado en esto y nos permite mapear todas las excepciones a
un conjunto de excepciones propias de tipo uncheked)
..
Y llegados a este punto he de decir que no trabajo para SpringSource ni VMware (aunque no estara
nada mal), ni me pagan por escribir todo esto; simplemente quera compartir con todos vosotros
mis pensamientos y sentimientos sobre Spring y animar encarecidamente a todos los que queris
probarlo a hacerlo, porque cuanto ms te adentras en el funcionamiento de Springms te
engancha; y si antes os preguntbais: Y para qu sirve Spring? o Para qu voy a utilizarlo? .
veris como la cosa cambia a: Cmo NO voy a utilizar Spring?
Y ya sabis cualquier mejora, sugerencia, propuesta, duda ser siempre bien recibida ;)