Inyección de Dependencias (DI) en Spring

En el tutorial IoC con Spring vimos como los beans son administrados por Spring IoC Container, en ocasiones podemos tener beans que dependen de otros, estos a su vez tienen sus dependencias, la inyección de dependencias en un patrón de diseño en el cual estas dependencias son inyectadas automáticamente por el framework, en nuestro caso Spring Framework.

Spring maneja dos tipos de inyección de dependencias, Constructor Injection y Setter Injection, el primero inyecta las dependencias utilizando el constructor de la clase, el segundo utilizando el correspondiente método setter.

Para ejemplificar usaremos dos clases, la primera llamada Estudiante y la segunda llamada Profesor, la clase Profesor maneja una referencia a la clase Estudiante, esta es la dependencia.

public class Estudiante {
    @Override
    public String toString() {
        return "estudiante: Pedro.";
    }
}

En la clase Profesor creamos un constructor vacío y otro que recibe un estudiante, creamos también el correspondiente método setter para el campo estudiante.

public class Profesor {

    private Estudiante estudiante;

    public Profesor() {
    }

    public Profesor(Estudiante estudiante) {
        this.estudiante = estudiante;
    }

    public void setEstudiante(Estudiante estudiante) {
        this.estudiante = estudiante;
    }

    @Override
    public String toString() {
        return "Soy en profesor: Juan, imparto clases al " + estudiante;
    }
}

Para configurar el Contenedor IoC de Spring usaremos código java, la anotación @Configuration sobre la clase nos permite utilizar @Bean para agregar los beans profesor y estudiante al contenedor Spring.

@Configuration
public class SpringConfiguration {

    @Bean
    public Profesor profesor(){
        return new Profesor(estudiante());
    }

    @Bean
    public Estudiante estudiante(){
        return new Estudiante();
    }
}

Al crear el bean profesor usamos el constructor para enviar la referencia al objeto estudiante, así de fácil usamos Constructor Injection, de manera similar podremos utilizar Setter Injection, veamos:

@Bean
public Profesor profesor(){
//  Constructor Injection
//  return new Profesor(estudiante());

//  Setter Injection
    Profesor profesor = new Profesor();
    profesor.setEstudiante(estudiante());
    return profesor;
}

En el tutorial anterior IoC con Spring indicamos la configuración el constructor de la clase AnnotationConfigApplicationContext para iniciar el contenedor Spring, otra forma de hacerlo es usando el constructor vacío, luego usar el método register para agregar la configuración y finalmente el método refresh para cargar la configuración.

public class Main {
    public static void main(String[] args){
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
        ctx.register(SpringConfiguration.class);
        ctx.refresh();

        Profesor profesor = ctx.getBean(Profesor.class);
        System.out.println(profesor);
    }
}

Inyección de Dependencias usando @Autowired


Primero veamos una manera más sencilla de crear beans, en lugar de usar @Bean para definir cada componente administrado por el IoC Container podemos marcar cada clase con la anotación @Component, en nuestro ejemplo anotaremos las clases Profesor y Estudiante, tenemos también que indicarle al contenedor Spring donde encontrar los componentes, usamos la anotación @ComponentScan({“carmelo.test.di.beans”}) indicando el paquete donde se encuentran los componentes, con esto Spring buscara en el o los paquetes indicados las clases anotadas con @Component o derivados y creara los beans para cada uno de ellos.

@Configuration
@ComponentScan({"carmelo.test.di.beans"})
public class SpringConfiguration { }

Podemos utilizar ctx.scan("carmelo.test.di.beans"); para indicar los paquetes que Spring debe analizar en búsqueda de componentes.

Si ejecutamos veremos que profesor no tiene asignado una referencia a estudiante, por lo debemos indicar como se inyectan las dependencias, la anotación @Autowired indica a Spring que debe buscar el bean apropiado e inyectarlo, podemos usarla en el constructor (Constructor Injection), en el método setter (Setter Injection) o sobre el campo de la clase, este último caso usara reflexión para inyectar la referencia.

@Component
public class Profesor {

    @Autowired
    private Estudiante estudiante;

    public Profesor() {
    }

//    @Autowired // Constructor Injection
    public Profesor(Estudiante estudiante) {
        this.estudiante = estudiante;
    }

//    @Autowired // Setter Injection
    public void setEstudiante(Estudiante estudiante) {
        this.estudiante = estudiante;
    }

    @Override
    public String toString() {
        return "Soy en profesor: Juan, imparto clases al " + estudiante;
    }
}

GitHub: DI con Spring

Comentarios

Temas relacionados

Entradas populares de este blog

tkinter Grid

Conectar SQL Server con Java

Histogramas OpenCV Python

Controles y Contenedores JavaFX 8 - I