modal interfaz grafica ejemplo componentes java spring dependency-injection required

java - interfaz - jlabel



Explica por qué la inyección de constructor es mejor que otras opciones (8)

(...) mediante el uso de la inyección de constructor, usted afirma el requisito de la dependencia de una manera independiente del contenedor

Esto significa que puede hacer cumplir los requisitos para todos los campos inyectados sin utilizar ninguna solución específica de contenedor .

Ejemplo de inyección Setter

Con inyección setter, se requiere una anotación de resorte especial @Required .

@Necesario

Marca un método (por lo general, un método de configuración JavaBean) como '' requerido '': es decir, el método setter debe configurarse para inyectarse con un valor.

Uso

import org.springframework.beans.factory.annotation.Required; import javax.inject.Inject; import javax.inject.Named; @Named public class Foo { private Bar bar; @Inject @Required public void setBar(Bar bar) { this.bar = bar; } }

Ejemplo de inyección de constructor

Todos los campos requeridos se definen en el constructor, solución pura de Java.

Uso

import javax.inject.Inject; import javax.inject.Named; @Named public class Foo { private Bar bar; @Inject public Foo(Bar bar) { this.bar = bar; } }

Esta pregunta ya tiene una respuesta aquí:

En un libro de Pro Spring 3, Capítulo 4 - Introducción IOC y DI en Spring - Página 59, en la sección "Inyección de Setter frente a Inyección de Constructor", un párrafo dice

Incluido Spring, proporcione un mecanismo para garantizar que todas las dependencias se definan cuando usa Setter Injection, pero al usar Constructor Injection, afirma el requerimiento para la dependencia de una manera independiente del contenedor "

Podrías explicar con ejemplos


Al usar la inyección de Constructor, usted afirma el requisito de la dependencia de una manera independiente del contenedor

Necesitamos la garantía del contenedor IoC de que, antes de usar cualquier grano, se debe hacer la inyección de los granos necesarios.

En la estrategia de inyección setter , confiamos en el contenedor IoC que primero creará el bean primero, pero hará la inyección justo antes de usar el bean utilizando los métodos setter. Y la inyección se realiza de acuerdo a su configuración. Si de alguna manera falla al especificar cualquier frijol para inyectar en la configuración, la inyección no se hará para esos granos y su bean dependiente no funcionará en consecuencia cuando esté en uso.

Pero en la estrategia de inyección de constructores , el contenedor impone (o debe imponer) proporcionar las dependencias adecuadamente al construir el bean. Esto fue abordado como "manera independiente del contenedor" , ya que estamos obligados a proporcionar dependencias al crear el bean, lo que hace que la visibilidad de la dependencia sea independiente de cualquier contenedor IoC.

Editar:

P1: ¿Y cómo evitar que el contenedor cree bean por constructor con valores null lugar de perder beans?

No tiene opción de perder realmente ningún <constructor-arg> (en el caso de Spring), ya que el contenedor IoC le impone la obligación de proporcionar todos los argumentos de constructor necesarios para que coincida con un constructor proporcionado para crear el bean. Si proporciona null en su <constructor-arg> intencionalmente. ¡Entonces no hay nada que el contenedor IoC pueda hacer o necesite hacer con él!


  1. Dependencia parcial: se puede inyectar utilizando la inyección de setter pero no es posible por el constructor. Supongamos que hay 3 propiedades en una clase, que tienen 3 métodos arg constructor y setters. En tal caso, si desea pasar información para una sola propiedad, solo es posible mediante el método setter.
  2. Anulación: la inyección Setter anula la inyección del constructor. Si usamos tanto la inyección de constructor como la de setter, el contenedor de IOC usará la inyección setter.
  3. Cambios: podemos cambiar fácilmente el valor mediante la inyección del colocador. No crea una nueva instancia de bean siempre como constructor. Así que la inyección de setter es más flexible que la inyección de constructor

Con ejemplos? Aquí hay uno simple:

public class TwoInjectionStyles { private Foo foo; // Constructor injection public TwoInjectionStyles(Foo f) { this.foo = f; } // Setting injection public void setFoo(Foo f) { this.foo = f; } }

Personalmente, prefiero la inyección de constructor cuando puedo.

En ambos casos, la fábrica de TwoInjectionStyles ejemplifica las instancias de TwoInjectionStyles y Foo y otorga a la primera su dependencia de Foo .


Este ejemplo puede ayudar:

Clase de controlador:

@RestController @RequestMapping("/abc/dev") @Scope(value = WebApplicationContext.SCOPE_REQUEST) public class MyController { //Setter Injection @Resource(name="configBlack") public void setColor(Color c) { System.out.println("Injecting setter"); this.blackColor = c; } public Color getColor() { return this.blackColor; } public MyController() { super(); } Color nred; Color nblack; //Constructor injection @Autowired public MyController(@Qualifier("constBlack")Color b, @Qualifier("constRed")Color r) { this.nred = r; this.nblack = b; } private Color blackColor; //Field injection @Autowired private Color black; //Field injection @Resource(name="configRed") private Color red; @RequestMapping(value = "/customers", produces = { "application/text" }, method = RequestMethod.GET) @ResponseStatus(value = HttpStatus.CREATED) public String createCustomer() { System.out.println("Field injection red: " + red.getName()); System.out.println("Field injection: " + black.getName()); System.out.println("Setter injection black: " + blackColor.getName()); System.out.println("Constructor inject nred: " + nred.getName()); System.out.println("Constructor inject nblack: " + nblack.getName()); MyController mc = new MyController(); mc.setColor(new Red("No injection red")); System.out.println("No injection : " + mc.getColor().getName()); return "Hello"; } }

Color de interfaz:

public interface Color { public String getName(); }

Clase roja:

@Component public class Red implements Color{ private String name; @Override public String getName() { return name; } public void setName(String name) { this.name = name; } public Red(String name) { System.out.println("Red color: "+ name); this.name = name; } public Red() { System.out.println("Red color default constructor"); } }

Clase Black:

@Component public class Black implements Color{ private String name; @Override public String getName() { return name; } public void setName(String name) { this.name = name; } public Black(String name) { System.out.println("Black color: "+ name); this.name = name; } public Black() { System.out.println("Black color default constructor"); } }

Clase de configuración para crear beans:

@Configuration public class Config { @Bean(name = "configRed") public Red getRedInstance() { Red red = new Red(); red.setName("Config red"); return red; } @Bean(name = "configBlack") public Black getBlackInstance() { Black black = new Black(); black.setName("config Black"); return black; } @Bean(name = "constRed") public Red getConstRedInstance() { Red red = new Red(); red.setName("Config const red"); return red; } @Bean(name = "constBlack") public Black getConstBlackInstance() { Black black = new Black(); black.setName("config const Black"); return black; } }

BootApplication (clase principal):

@SpringBootApplication @ComponentScan(basePackages = {"com"}) public class BootApplication { public static void main(String[] args) { SpringApplication.run(BootApplication.class, args); } }

Ejecute la aplicación y pulse la URL: GET 127.0.0.1:8080/abc/dev/customers/

Output: Injecting setter Field injection red: Config red Field injection: null Setter injection black: config Black Constructor inject nred: Config const red Constructor inject nblack: config const Black Red color: No injection red Injecting setter No injection : No injection red


La inyección de constructores se usa cuando la clase no puede funcionar sin la clase dependiente.

La inyección de propiedad se usa cuando la clase puede funcionar sin la clase dependiente.

Como ejemplo concreto, considere un ServiceRepository que depende de IService para hacer su trabajo. Como ServiceRepository no puede funcionar de manera útil sin IService, tiene sentido que se lo inyecte a través del constructor.

La misma clase ServiceRepository puede usar un Logger para realizar el seguimiento. El ILogger se puede inyectar mediante la inyección de propiedades.

Otros ejemplos comunes de inyección de propiedad son ICache (otro aspecto en la terminología de AOP) o IBaseProperty (una propiedad en la clase base).


Para hacerlo simple, digamos que podemos usar inyección de dependencia basada en constructor para dependencias obligatorias e inyección basada en setter para dependencias opcionales. ¡Es una regla general!

Digamos por ejemplo.

Si desea instanciar una clase, siempre lo hace con su constructor. Entonces, si está utilizando inyección basada en el constructor, la única forma de instanciar la clase es a través de ese constructor. Si pasa la dependencia a través del constructor, se hace evidente que se trata de una dependencia obligatoria.

Por otro lado, si tiene un método setter en una clase POJO, puede o no establecer un valor para su variable de clase utilizando ese método setter. Está completamente basado en tu necesidad. es decir, es opcional. Entonces, si pasas la dependencia a través del método setter de una clase, implícitamente significa que es una dependencia opcional. Espero que esto esté claro !!


Una clase que toma una dependencia requerida como un argumento constructor solo se puede instanciar si se proporciona ese argumento (debe tener una cláusula guard para asegurarse de que el argumento no sea nulo.) Por lo tanto, un constructor impone el requisito de dependencia independientemente de que sea o no usando Spring, haciéndolo agnóstico de contenedor.

Si utiliza la inyección setter, el setter puede o no ser llamado, por lo que la instancia nunca puede ser proporcionada con su dependencia. La única forma de forzar al usuario del setter es usar @Required o @Autowired , que es específico de Spring y, por lo tanto, no es independiente del contenedor.

Para mantener su código independiente de Spring, use los argumentos de constructor para la inyección.

Actualización : Spring 4.3 realizará la inyección implícita en escenarios de un solo constructor , lo que hará que el código sea más independiente de Spring al no necesitar una anotación @Autowired .