Como sé, no se recomienda field injection
. Debería usar constructor
en su lugar.
Lo que estoy tratando de hacer aquí es usar @Autowired
en el constructor de la clase base y hacerlo accesible para todas las subclases. En algunas subclases, también necesito que algunos beans específicos sean @Autowired
de sus constructores. El código de demostración es el siguiente:
Clase base:
public abstract class Base { protected final MyDemoService myDemoService; @Autowired public Base(MyDemoService myDemoService) { this.myDemoService = myDemoService; } }
Clase heredada (sub):
public class Sub extends Base { private final MySubService mySubService; @Autowired public Sub(MySubService mySubService) { this.mySubService = mySubService; } }
Esto me dará un error de "constructor no predeterminado".
Es similar a la pregunta: similar pregunta y respuesta , pero no funciona aquí.
Me he sumergido en esto por un tiempo, encontré este artículo sobre dependency injection
:leer más
Estoy pensando que la Setter Injection
es la forma correcta de responder a mi pregunta.
Inyección de fijador:
public abstract class Base { protected MyDemoService myDemoService; @Autowired public void setMyDemoService(MyDemoService myDemoService) { this.myDemoService = myDemoService; } }
Soy nuevo en Java Spring Boot y quiero obtener algunos consejos de ustedes. ¡Cualquier discusión será muy apreciada!
El código que proporcione no se compilará. Siempre que en su clase base no tenga el constructor predeterminado, debe llamar a super(MyDemoService)
en child.
Clase heredada (sub):
public class Sub extends Base { private final MySubService mySubService; @Autowired public Sub(MySubService mySubService, MyDemoService myDemoService){ super(myDemoService); this.mySubService = mySubService; } }
O, si MySubService
es una implementación de MyDemoService
@Autowired public Sub(MySubService mySubService){ super(mySubService); }
Mientras su campo MyDemoService myDemoService
en clase abstracta esté protected
, puede usarlo en subclases.
Si tiene una implementación múltiple de MyDemoService
, debe usar @Qualifier
como se describe en la respuesta que ha mencionado .
public Sub(@Qualifier("MySubService") MyDemoService mySubService){ super(mySubService); }
No use inyección de campo, use inyección de constructor llamando a los súper constructores según corresponda.
La inyección de constructor garantiza que su objeto se complete correctamente antes de la creación de instancias, la inyección de setter no lo hace y hace que el código sea más propenso a errores (no otro error de puntero nulo ...)
Si le preocupa el código adicional que tiene que escribir, use Project Lombok para permitir que Lombok genere el código del constructor por usted como se describe aquí. Por qué la inyección de campo es mala
Por cierto, a partir de Spring 4, si solo tiene un constructor en su clase, no necesita @Autowired en el constructor.
Sugeriría usar clases @Configuration
. De esa manera, puede eliminar las anotaciones de Spring por completo de sus clases de negocios:
public class Sub extends Base { private final MySubService mySubService; public Sub(MySubService mySubService, MyDemoService myDemoService){ super(myDemoService); this.mySubService = mySubService; } }
Configuración de primavera:
@Configuration public class SubConfig{ @Bean public Sub sub(MySubService subService, MyDemoService demoService){ return new Sub(subService, demoService); } }
Con las clases de configuración, ya no confía en el escaneo mágico de classpath, sino que en realidad vuelve a crear instancias de beans manualmente. Hay muchas menos sorpresas en este enfoque.