2011-10-15 13 views
14

Spring tiene dos dos tipos de DI: setter DI y construcción DI.Setter DI vs. Constructor DI en Spring?

La DI basada en el constructor arregla el orden en que las dependencias deben ser inyectadas. La DI basada en Setter no ofrece esto.

DI basado en Setter nos ayuda a inyectar la dependencia solo cuando es necesario, en lugar de necesitarla en el momento de la construcción.

No veo ninguna otra diferencia significativa, ya que ambos tipos de Spring DI ofrecen las mismas características: tanto setter como constructor DI inyectan la dependencia cuando se inicia el código. Por supuesto, el constructor DI lo hará a través del constructor mientras que el setter DI lo hará a través de un setter justo después de construir el objeto, pero no hace ninguna diferencia para el desarrollador en términos de rendimiento, etc. Ambos también ofrecen medios para especificar el orden de la inyección de dependencia también.

Estoy buscando un escenario donde uno proporciona una ventaja distintiva sobre el otro o donde un tipo es completamente inutilizable.

+0

http://stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it – GKislin

Respuesta

14

Cuando se trata de primavera pros y los contras específicos:

  • Constructor de inyección (de la definición) no le permiten crear dependencias circulares entre los granos. Esta limitación es en realidad una ventaja de la inyección de constructor: Spring puede resolver dependencias circulares cuando se usa la inyección de setter sin que se dé cuenta.

  • Por otro lado, si utiliza la inyección de constructor, CGLIB no puede crear un proxy, lo que le obliga a utilizar proxies basados ​​en interfaz o un constructor ficticio no-arg. Ver: SPR-3150

+0

Gracias Tomasz.Point1: - ¿La primavera da error de tiempo de ejecución en caso de circular ¿dependencia? Punto2: -Apenas trato de entender con el ejemplo. ¿Estás diciendo que si tengo la clase A que está usando la Clase B como dependencia en su constructor (la clase B no implementa la interfaz). ¿Será posible? –

+1

Piénselo: si bean A requiere una instancia de bean B en el inicio y bean B requiere una instancia de bean A, no hay forma de crear una instancia de ellos. Cuando Spring detecta tal situación, lanza una excepción al comenzar. Sin embargo, con inyección setter/campo Spring puede primero crear instancias y luego inyectarlas, no hay problema en esta situación. –

+1

Si este es un problema común en su proyecto, entonces probablemente tenga otras cosas de qué preocuparse que el estilo DI. –

12

Debe decidir basándose en consideraciones de diseño, no en consideraciones de herramientas (primavera). Desafortunadamente, Spring nos ha capacitado para usar la inyección setter porque cuando se concibió originalmente, no existía una "anotación" en Java, y en XML, la inyección setter funciona y se ve mucho mejor. Hoy, estamos liberados de esas limitaciones, lo que permite que sea una decisión de diseño nuevamente. Sus beans deben usar inyección de constructor para las dependencias requeridas por la inyección de bean y setter para las dependencias que son opcionales y tienen un valor predeterminado razonable, más o menos como OOD nos ha estado diciendo desde el principio.

+1

Gracias Ryan. Como usted dijo "Sus beans deberían usar inyección de constructor para cualquier dependencia que requiera la inyección de set y bean para dependencias que son opcionales y tienen un valor por defecto razonable". Esto es lo que estoy tratando de entender aquí en términos de primavera, incluso cuando la dependencia es opcional, framework lo inyectará al principio. ¿Qué diferencia hay en la vida del desarrollador? –

+0

* Cuando * algo está inyectado y * si * algo está inyectado son dos preguntas distintas. Las dependencias opcionales caen en el lado "si". –

0

Preferir la inyección del colocador.

Piensa en lo que sería sin primavera (como lo notó Ryan). ¿Pasarías las dependencias en el constructor? Si hay demasiadas dependencias, esto parece incorrecto. Por otro lado, el constructor puede utilizarse para aplicar el estado válido del objeto: requiere todas las dependencias y verifica si no son nulas.

Los apoderados son otra cosa (como señaló Tomasz): necesitarás un constructor ficticio que anule la idea.

Hay una tercera opción, por cierto, inyección de campo. Tiendo a usar eso, aunque no es una buena decisión de diseño, porque ahorra un setter extra, pero si se usa fuera de la primavera, tendré que agregar el setter.

+0

De hecho, usar la inyección de constructor tiene el beneficio adicional de hacer que sus granos mal diseñados sean dolorosamente obvios debido a los enormes constructores. Los proxies dinámicos JDK no necesitan constructores por defecto. Otros marcos se alejan de los constructores por defecto o requieren solo uno privado. La inyección de campo es mi segunda opción, pero luego están las pruebas ... –

+0

yup, para las pruebas hay ReflectionTestUtils. Lo cual es un poco feo – Bozho

2

Constructor Inyección: Estamos inyectando las dependencias a través de Constructor.

Generalmente podemos usar para Dependencias obligatorias.

Si utiliza la inyección Constructor existe una desventaja llamada "Dependencia circular".

Dependencia circular: Suponer A y B. A depende de B. B depende de A. En este constructor la inyección fallará. En ese momento, la inyección de Setter es útil.

Si el estado del Objeto no es inconsistente, no creará el Objeto.

Setter Injection: Estamos inyectando las dependencias a través de métodos Setter.

Esto es útil para Dependencias no obligatorias.

Es posible volver a inyectar dependencias mediante el uso de inyección del organismo. Es no es posible en Constructor de inyección.

0

no, incluso se produce la inyección de Constructor, la inyección sigue funcionando, pero la inicialización es limitada, la inyección del dispositivo es opcional y flexible. pero puede generalmente para la clase de parámetros, de un grano de primavera con otros granos de primavera

0

Ya que se puede mezclar tanto,
Constructor DI - y DI basada en Setter,
es una buena regla del pulgar a usa argumentos de constructor para dependencias obligatorias y establecedores para dependencias opcionales.


Nota que el uso de una anotación @Required en un setter se puede usar para establecer dependencias requeridas por los setters.

Cuestiones relacionadas