La DI basada en Setter se realiza mediante el contenedor que llama a setters en beans después de llamar a un constructor sin argumentos o a un método de fábrica static sin argumentos para crear una instancia del bean.

El siguiente ejemplo muestra una clase cuya dependencia solo se puede inyectar a través de un definidor. Esta clase es una clase Java normal. Es un POJO (objeto Java simple) que no depende de interfaces de contenedor, clases base o anotaciones específicas.

Java

public class SimpleMovieLister {
    // SimpleMovieLister depends on MovieFinder
    private MovieFinder movieFinder;
    // setter to allow the Spring container to implement MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // business logic that actually uses the embedded MovieFinder is omitted...
}
Kotlin
class SimpleMovieLister {
    // lazy-initialized property that allows the Spring container to implement MovieFinder
    lateinit var movieFinder: MovieFinder
    // business logic that actually uses the embedded MovieFinder is omitted...
}

ApplicationContext admite DI basada en constructor y definidor para los beans que administra. También admite DI basada en setter después de que algunas dependencias ya se hayan inyectado utilizando el enfoque del constructor. Las dependencias se configuran en forma de BeanDefinition, que se utiliza junto con instancias de PropertyEditor para convertir propiedades de un formato a otro. Sin embargo, la mayoría de los usuarios de Spring trabajan con estas clases no directamente (es decir, mediante programación), sino con definiciones XML bean componentes anotados (es decir, clases marcadas con @Component, anotaciones). @Controller y así sucesivamente) o métodos marcados con la anotación @Bean en clases basadas en Java marcadas con la anotación @Configuration . Estas fuentes luego se convierten internamente en instancias BeanDefinition y se usan para cargar toda la instancia del contenedor Spring IoC.

¿DI basada en constructor o basada en definidor?

Debido a que es posible mezclar DI basada en constructor y DI basada en definidor, una buena regla general es usar constructores para las dependencias requeridas y definidores o métodos de configuración para dependencias opcionales. Tenga en cuenta que se puede utilizar la anotación @Required en un definidor para convertir una propiedad en una dependencia requerida; sin embargo, es preferible utilizar la inyección de constructor con verificación programática de argumentos.

El equipo de Spring generalmente admite la inyección de constructores porque permite que los componentes de la aplicación se implementen como objetos inmutables y garantiza que las dependencias requeridas no sean null. Además, los componentes inyectados a través del constructor siempre se devuelven al código del cliente (de llamada) en un estado completamente inicializado. Como nota al margen, tener muchos argumentos de constructor huele a código, lo que significa que la clase probablemente esté sobrecargada y deba refactorizarse para distribuir mejor las tareas.

La inyección de definidor debe usarse principalmente solo para dependencias opcionales a las que se les pueden dar valores predeterminados razonables en la clase. De lo contrario, se debe realizar una verificación de que no sea nulo siempre que se utilice una dependencia en el código. Uno de los beneficios de la inyección de setter es que los métodos de setter hacen que los objetos de la clase sean adecuados para una reconfiguración o reinyección posterior. Por lo tanto, la gestión mediante JMX MBeans es un ejemplo adecuado del uso de la inyección de setter.

Utilice el estilo DI que sea más apropiado para la clase específica. A veces, cuando se trata de clases de terceros para las cuales no tienes el código fuente, la elección la haces tú. Por ejemplo, si la clase de terceros no expone ningún método de establecimiento, entonces la inyección del constructor puede ser la única forma de inyección de dependencia disponible.