how - spring injection constructor
Cómo configurar los parámetros del constructor @Autowired como "requerido=falso" individualmente (3)
Estoy usando la anotación @Autowired
en un constructor de clase @Configuration
.
@Configuration
public class MyConfiguration {
private MyServiceA myServiceA;
private MyServiceB myServiceB
@Autowired
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
}
Como se indica en la documentación de Spring , puedo declarar si se requiere la dependencia anotada.
Si marco la anotación @Autowired
bajo el constructor como required=false
, estoy diciendo que no se requieren los dos servicios para ser autowired (como lo indica la documentación de Spring) :
@Autowired(required = false)
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
De la documentación de primavera:
En el caso de los métodos de múltiples argumentos, el parámetro ''requerido'' es aplicable para todos los argumentos.
¿Cómo puedo establecer el atributo required
para cada parámetro de constructor individualmente? ¿Es necesario usar la anotación @Autowired
en cada campo?
Saludos,
Desde la primavera 4.3.0.RC1 puedes hacer esto:
public MyConfiguration(MyServiceA myServiceA, @Autowired(required = false) MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
Como ElementType.PARAMETER
se agregó como destino de anotación.
Si está utilizando Java 8 y Spring Framework 4, puede usar Optional
.
@Autowired
public MyConfiguration(Optional<MyServiceA> myServiceA, Optional<MyServiceB> myServiceB){
myServiceA.ifPresent(service->{this.myServiceA = service});
myServiceB.ifPresent(service->{this.myServiceB = service});
}
Enfoque explícito
Básicamente, usted tiene un bean que tiene algunas dependencias requeridas y opcionales. La forma recomendada de manejar este escenario, no solo los beans de configuración, sino cualquier otro, es crear un constructor solo para las dependencias obligatorias y usar la inyección del definidor para los opcionales.
public class MyConfiguration {
private final MyServiceA myServiceA;
private MyServiceB myServiceB
@Autowired
public MyConfiguration(MyServiceA myServiceA){
this.myServiceA = myServiceA;
}
@Autowired(required = false)
public void setMyServiceB(MyServiceB myServiceB) {
this.myServiceB = myServiceB;
}
}
Con este enfoque, puede realizar fácilmente pruebas unitarias de la clase sin necesidad de ninguna biblioteca de burla. Puede crear un objeto en estado de prueba utilizando el constructor y los configuradores opcionales.
Poner @Autowired(required = false)
directamente en el campo y eliminar el configurador también funcionará, pero como está usando la inyección del constructor, asumo que desea declarar las dependencias más explícitamente.
Idea adicional
También puede considerar el uso del tipo Opcional para ajustar dependencias no obligatorias. Es común que los desarrolladores asuman que si una clase tiene una propiedad, debería configurarse, lo que obviamente no es correcto en su escenario. Para marcar con mayor claridad la posibilidad de ausencia para dependencias particulares, probablemente pueda usar Opcional:
public class MyConfiguration {
private final MyServiceA myServiceA;
private Optional<MyServiceB> myServiceB
@Autowired
public MyConfiguration(MyServiceA myServiceA){
this.myServiceA = myServiceA;
this.myServiceB = Optional.empty();
}
@Autowired(required = false)
public void setMyServiceB(MyServiceB myServiceB) {
this.myServiceB = Optional.ofNullable(myServiceB);
}
}
Algunas personas están en contra del uso del tipo Optional
para propiedades de clase (principalmente debido a esta respuesta de Brian Goetz ), pero al final del día, debe ser la decisión que tome todo el equipo que trabajará en el proyecto.