pcollaog
(20 comments, 173 posts)
This user hasn't shared any profile information
Home page: http://blog.pcollaog.cl
Jabber/GTalk: pcollaog@gmail.com
Posts by pcollaog
¿Por que FactoryBean<T> es útil?
1En este post voy a tratar de explicar porque FactoryBean<T> es increíblemente útil para alambrar (aplicar DI) aplicaciones hechas con Spring Framework.
La interfaz de FactoryBean dice lo siguiente:
public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }
La utilidad de la implementación de esta interfaz y su posterior declaración como Bean dentro del contexto de la aplicación, es que puede ser usada (como su nombre lo indica) como Factory para inyectar algún valor en alguna propiedad de otro Bean.
¿Dónde y cómo funciona? Dentro del ciclo de vida de la carga del Contexto de spring, la ejecución de la implementación de esta interfaz, esta justo antes de hacer los setters de las propiedades de un Bean. El funcionamiento es simple, siempre se ejecutará el método getObject() que retornará la instancia del tipo T.
Veamos una implementación simple y una configuración de contexto de spring:
public class RandomNumberFactoryBean implements FactoryBean<Integer> { public Integer getObject() throws Exception { return Integer.valueOf(new Random().nextInt()); } public Class<?> getObjectType() { return Integer.class; } public boolean isSingleton() { return true; } }
Esta simple implementación de FactoryBean
El método getObjectType() es usado internamente por el framework para validar que el retorno de getObject() sea correcto o que este dentro de la jerarquía de clases, esto es en caso de que quieras restringir por tipo.
El último método isSingleton() es si quieres que esta clase (no importa la cantidad de declaraciones que tengas, siempre será la misma), es un tanto dificil de entender pero les sugiero que lean sobre el concepto de Singleton que tiene SpringFramework. En el ejemplo de configuración espero que les quede claro, de lo contrario, bienvenidas las preguntas.
Esta es la definición del Bean de ejemplo, en donde se hará uso del FactoryBean:
public class ExampleBean { private Integer _randomValue; public final Integer getRandomValue() { return _randomValue; } public final void setRandomValue(Integer randomValue) { _randomValue = randomValue; } }
Aquí las configuraciones de contexto de spring.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- Ejemplo 1 --> <bean id="exampleBean1" class="cl.pcollaog.factory.ExampleBean"> <property name="randomValue"> <bean class="cl.pcollaog.factory.RandomNumberFactoryBean" /> </property> </bean> <!-- Ejemplo 2 --> <bean id="randomNumberFactoryBean" class="cl.pcollaog.factory.RandomNumberFactoryBean" /> <bean id="exampleBean21" class="cl.pcollaog.factory.ExampleBean"> <property name="randomValue" ref="randomNumberFactoryBean" /> </bean> <bean id="exampleBean22" class="cl.pcollaog.factory.ExampleBean"> <property name="randomValue" ref="randomNumberFactoryBean" /> </bean> </beans>
Ejemplo 1:
Se declara el Bean exampleBean1 y que tiene como propiedad el atributo randomValue y cuyo valor será producto de la ejecución del Bean RandomNumberFactoryBean en el momento que el contexto de Spring es cargado. En este caso se utiliza la técnica de InnerBean, es decir, no se tiene una instancia del Bean para ser reutilizada sino que esta en la misma declaración del setter del atributo.
Ejemplo 2:
Este ejemplo hace lo mismo indicado arriba, sólo que no se aplica InnerBean sino que se extrae y es reutilizado en el bean exampleBean21 y exampleBean22. En este ejemplo entra en juego el método isSingleton(), si es true, quiere decir que el valor que entregará el FactoryBean siempre será el mismo para ambos Beans. Ahora bien, si se cambia a false, por cada setter, es decir, para exampleBean21 y exampleBean22 se realizara la ejecución de RandomNumberFactoryBean 2 veces. (En este caso, nos entregará dos valores aleatorios para cada bean)
En pocas palabras para cada Bean del ejemplo 2 habrá dos instancias de RandomNumberFactoryBean que entregará cada una un Integer para los atributos de los beans declarados.
Algo interesante de las implementaciones de FactoryBean
Espero les sea útil y cualquier pregunta sera bienvenida.
Java7: null-safe y null-default
0Seguramente les ha pasado y mucho que tienen que llenarse de validaciones contra NullPointerException cuando los métodos retornan null, hay una propuesta para poder manejar este tipo de problemas. Veamos uno ejemplos:
Null-Default
Hoy en dia:
String maybeNull = metodoNull(); if (null == maybeNull) { maybeNull="Ahora no es null"; } // Otra Opcion String nullVar = metodoNull(); nullVar = (nullVar != null ? nullVar : "Ahora no es null");
Ahora la propuesta es la siguiente:
String maybeNull = metodoMaybeNull(); maybeNull = maybeNull ?: "Ahora no es null";
Como verán nos ahorramos unas cuantas líneas de código. Ahora veamos el otro esquema
Null-safe
Hoy en dia:
String result = null;
Foo foo = getFooMayBeNull();
if (foo != null) {
Bar bar = foo.getBarMayBeNull();
if (bar != null) {
result = bar.getResult();
}
}
Con la propuesta de null-safe quedaría así:
String result = getFooMayBeNull()?.getBarMayBeNull()?.getResult();
Esto hasta el dia de hoy seguía en propuesta y por lo que veo en las Características de Java7 no viene, así que a esperar. (Estoy bajando el jdk7 para probar, luego updates)
Estas modificaciones al lenguaje (sintaxis) vienen de los operadores que tiene Goovy.
Más información sobre esta propuesta de mejora al lenguaje en:
Algunas API’s Java que te pueden servir: commons-io
2commons-io trae un montón de clases que te pueden servir al momento de utilizar lecturas y escrituras de archivos, entre otras cosillas.
Por si no lo sabías una de las malas practicas mas recurrentes programando con java es, no cerrar los Stream y ciertos Readers adecuadamente, o te complicas mucho con los try/catch, vamos a ver un par de ejemplos clásicos:
Primero agregamos la dependencia de maven, ojo que las versiones 2.x están escritas para Java 1.5 y las 1.x para java 1.3 y 1.4:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.0.1</version> </dependency>
Caso 1: finally que asegura cerrar el Reader con el método close()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public void closeWithFinally(String filename) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(filename)); try { StringBuilder sb = new StringBuilder(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); } String contentFile = sb.toString(); System.out.println(contentFile); } finally { // Cerrar el reader reader.close(); } } |
Caso 2: Creando la instancia de BufferedReader dentro del try y validando si es null al momento de cerrar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public void closeWithFinallyNullCheck(String filename) throws IOException { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(filename)); String line = null; StringBuilder sb = new StringBuilder(); while ((line = reader.readLine()) != null) { sb.append(line); } String contentFile = sb.toString(); System.out.println(contentFile); } finally { // Cerrar el reader if (null != reader) { reader.close(); } } } |
Caso 3: Usando commons-io y la clase IOUtils se reduce bastante el código y quedaría algo así:
1 2 3 4 5 6 7 8 9 | public void closeWithFinallyCommonsIO(String filename) throws IOException { BufferedReader reader = new BufferedReader(new FileReader(filename)); try { String contentFile = IOUtils.toString(reader); System.out.println(contentFile); } finally { IOUtils.closeQuietly(reader); } } |
Mas información en el maven site del proyecto:
Mas adelante escribiré un par de ejemplos con otras clases de commons-io que son bastante útiles.
Cómo iterar un Map con Java 1.5
1A pedido del Sr: @perrefe les dejo un tip de performance para iterar sobre Map<K,V>:
Supongamos que nuestro Map
1 | Map<String,Integer> map = new HashMap<String,Integer>(); |
Ahora podemos iterar el Map de la siguiente forma:
1 2 3 4 | for (Entry<String, Integer> entry : map.entrySet()) { System.out.println("Key [" + entry.getKey() + "]"); System.out.println("Value [" + entry.getValue() + "]"); } |
Si ve por ahí algún iterador sobre un Map
Por favor no haga esto!!!
1 2 3 4 5 6 7 | Set<String> keys = map.keySet(); for (String key : keys) { Integer value = map.get(key); System.out.println("Key [" + key + "]"); System.out.println("Value [" + value + "]"); } |
Espero les sirva.

