Antes de leer este post, te recomiendo los anteriores para un mejor entendimiento:

En la parte 1 vimos como usar Spring siguiendo unos pasos lógicos. Una de esos pasos era el número 3 donde definiamos nuestros objetos(beans) y luego cargabamos esas definiciones en el contenedor. Esto lo hicimos con xml. Ahora veamos como hacer lo mismo sin usar xml, solo registrando nuestros objetos.

Como ya vimos si usas Maven la unica dependencia a incluir en el pom.xml es spring-beans ya que por transitividad se trae spring-core y commons-logging.

1
2
3
4
5
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-beans</artifactId>
   <version>4.0.5.RELEASE</version>
</dependency>


Sis los haces manualmente se necesita agregar al proyecto los siguientes jars:

  • spring-core-4.0.5.RELEASE.jar
  • spring-beans-4.0.5.RELEASE.jar
  • commons-logging-1.1.3.jar

Moficando el paso 3

Aquí ya no necesitamos el xml y también tenemos que modificar el codigo Java. Tenemos que crear las mismas definiciones del xml pero con codigo Java. Veamos como nos queda este paso 3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Creamos dos definiciones de beans

//Definicion para DotMatrixPrinter
GenericBeanDefinition dotMatrixPrinterDef = new GenericBeanDefinition();
dotMatrixPrinterDef.setBeanClass(DotMatrixprinter.class);

//Definicion para Office
GenericBeanDefinition officeDef = new GenericBeanDefinition();
officeDef.setBeanClass(Office.class);

//Recordemos que Office recibe por constructor una referencia de Printer
//asi que definimos esta relacion con ConstructorArgumentValues
ConstructorArgumentValues officeConstructorValues = new ConstructorArgumentValues();
officeConstructorValues.addGenericArgumentValue(dotMatrixPrinterDef);

//Establecemos dicha relacion con la definición de Office
officeDef.setConstructorArgumentValues(officeConstructorValues);

//Registramos nuestras deficiones en el contenedor
container.registerBeanDefinition("dotMatrixPrinter", dotMatrixPrinterDef);
container.registerBeanDefinition("office", officeDef);


Ya estamos listos para usar nuestro contenedor.

Uniendo todo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//1.
public class Main {

   public static void main(String[] args) {

      //2. 
      DefaultListableBeanFactory container = new DefaultListableBeanFactory();

      //3.
      GenericBeanDefinition dotMatrixPrinterDef = new GenericBeanDefinition();
      dotMatrixPrinterDef.setBeanClass(DotMatrixprinter.class);

      GenericBeanDefinition officeDef = new GenericBeanDefinition();
      officeDef.setBeanClass(Office.class);

      ConstructorArgumentValues officeConstructorValues = new ConstructorArgumentValues();
      officeConstructorValues.addGenericArgumentValue(dotMatrixPrinterDef);

      officeDef.setConstructorArgumentValues(officeConstructorValues);

      container.registerBeanDefinition("dotMatrixPrinter", dotMatrixPrinterDef);
      container.registerBeanDefinition("office", officeDef);

      //4.
      Office officeBean = container.getBean(Office.class);
      Office officeBean2 = container.getBean(Office.class);
      officeBean.setMessageToPrint("Hola mundo!!");
      officeBean.print();
   }
}


Esta es una de las tantas formas de usar Spring, en este caso sin XML solo con nuestras clases y código Java.

Código Fuente

Código fuente en gitHub

Definir Dependencias por XML

Cuando tenemos dependencias entre nuestras clases y usamos xml, creamos estas relaciones dentro el tag <bean>. Veamos algunos ejemplos.

Inyección por referencia a través del constructor

1
2
3
4
package x.y;
public class Foo {
  public Foo(Bar bar, Baz baz) {//...}
}
1
2
3
4
5
6
7
<bean id="foo" class="x.y.Foo">
    <constructor-arg ref="bar"/>
    <constructor-arg ref="baz"/>
</bean>

<bean id="bar" class="x.y.Bar"/>
<bean id="baz" class="x.y.Baz"/> 


Inyección por tipo a través del constructor

1
2
3
4
5
6
7
8
9
10
package examples;
public class ExampleBean {
  private int years;
  private String ultimateAnswer;

  public ExampleBean(int years, String ultimateAnswer) {
      this.years = years;
      this.ultimateAnswer = ultimateAnswer;
  }
}
1
2
3
4
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>


Inyección por indice(posición del parámetro) a través del constructor

1
2
3
4
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>


Inyección por nombre de argumento a través del constructor

1
2
3
4
<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>


Tambien podemos definir nuestras dependencias a través de atributos o setters de la clase. Para esto usamos el tag <property> dentro de <bean>. Este permite las siguientes formas:

  • <property name=”propiedad” value=”...” />
  • <property name=”propiedad” ref=”...” />

Inyección por setter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ExampleBean {

  private BeanUno beanOne;
  private BeanDos beanTwo;
  private int i;

  public void setBeanOne(BeanUno beanOne) {
      this.beanOne = beanOne;
  }

  public void setBeanTwo(BeanDos beanTwo) {
      this.beanTwo = beanTwo;
  }

  public void setIntegerProperty(int i) {
      this.i = i;
  }
}
1
2
3
4
5
6
7
8
<bean id="exampleBean" class="examples.ExampleBean">
    <property name="beanOne" ref="beanUno"/>
    <property name="beanTwo" ref="beanDos"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="beanUno" class="examples.BeanUno"/>
<bean id="beanDos" class="examples.BeanDos"/>


Definir dependencias por código

En la parte inicial vimos como usar la clase ConstructorArgumentValues para definir nuestras dependencias a través del constructor. También podemos definir dependencias por setter con la clase MutablePropertyValues. Imagenemos que nuestra clase Office no recibe un Printer a través del constructor si no de un setter setPrinter(), nuestro código seria algo asi:

1
2
3
MutablePropertyValues printerSetter = new MutablePropertyValues();
printerSetter.add("printer", dotMatrixPrinterDef);
officeDef.setPropertyValues(printerSetter);


Algo interesante con MutablePropertyValues es que podemos agregarle varias propiedades o setter por ejemplo:

1
2
3
4
5
MutablePropertyValues printerSetter = new MutablePropertyValues();
printerSetter.add("printer", dotMatrixPrinterDef);
printerSetter.add("setter1", algunValor);
printerSetter.add("setter2", otroValor);
officeDef.setPropertyValues(printerSetter);


Bueno espero este artículo haya ampliado tu comprensión sobre Spring, contenedores y dependencias.


Franky Villadiego

Volando hacia el desarrollo productivo!