Pregunta

Viniendo de un fondo C ++, tengo que dominar la complejidad de Java mundo y sus marcos. Mirando el marco de primavera para DI soy me resulta difícil creer que tengo que hacer que cada setter funcione que estará sujeto a DI público. ¿Ese requisito no rompe el principio de ocultación de información?

Por supuesto que quiero que la primavera pueda configurar algunas partes privadas de mi clases, pero ciertamente NO quiero que cada clase de cliente pueda hacer lo mismo.

¿Qué me estoy perdiendo aquí?

¿Fue útil?

Solución

Si codifica para interfaces , solo necesita exponer a los configuradores en las implementaciones. A medida que inyecta las interfaces en otras partes del sistema, no pueden acceder a los detalles de implementación o al estado de los objetos.

Otros consejos

Estoy de acuerdo con su punto, por eso prefiero la inyección del constructor.

Usted (puede) tener que hacer un setter, que informará al exterior de algunos de sus detalles internos, pero no hay necesidad de hacer un getter. Entonces, está revelando alguna información, pero en realidad no demasiada; no es realmente útil para otra cosa que no sea su propósito previsto.

Además, solo recomendaría usar anotaciones y @Autowired, en cuyo caso no es necesario hacer una configuración pública.

Si usa anotaciones de primavera (@Autowired) puede DI miembros privados.

Si opta por el acoplamiento flojo y la capacidad de prueba (de la unidad) en mi opinión, los resortes DI revelan información que no debe ocultarse.

Tenía básicamente la misma pregunta aquí:

Encapsulación en la era de los marcos

Creo que la respuesta podría ser la inyección del constructor. Exponer sus propiedades con setters hace que sea realmente difícil encapsular cualquier cosa y mantener un buen estado del objeto.

Nunca usé @Autowired, me gusta usar parámetros en los constructores, pero a veces es difícil entender qué significan los parámetros, especialmente si tienes muchos parámetros; en ese caso, prefiero usar el " Builder " enfoque descrito en Java efectivo. El constructor recibe el objeto de compilación (que tiene setters) y se construye con él. Los atributos inyectados de la clase son finales (inmutabilidad), el " Generador " La clase contiene setters pero no getters (no es necesario ya que lo declaramos como una clase interna de la clase que se está construyendo), y no es necesario crear setters solo para Spring:

<bean id="runnable" class="MyClass">
   <constructor-arg>
     <bean class="MyClass$Builder">
       <property name="p1" value="p1Value"/>
       <property name="p2" value="p2Value"/>
       <property name="p3" value="p3Value"/>
       <property name="p4" value="p4Value"/>
     </bean>
   </constructor-arg>
</bean>

Código de clase:

public class MyClass {
   private final String p1;
   private final String p2;
   private final String p3;
   private final String p4;
   public MyClass(Builder builder) {
      this.p1 = builder.p1;
      this.p2 = builder.p2;
      this.p3 = builder.p3;
      this.p4 = builder.p4;
   }

   ...

   public static class Builder {
      private String p1;
      private String p2;
      private String p3;
      private String p4;
      public void setP1(String p1) {
         this.p1 = p1;
      }
      ... and so on
   }
}

Supongo que es una compensación. Reduce las dependencias cableadas, pero potencialmente expone las agallas de su implementación. Con las abstracciones correctas, también puede reducir eso, pero luego aumenta la complejidad de la base del código (por ejemplo, tener una "Conexión" genérica que podría ser una conexión LDAP o una conexión SQL).

Personalmente, tampoco creo que usar la inyección del constructor ayude, porque es más conceptual.

Tendré que revisar @Autowire, aunque '.

tj

Solo quería mencionar que (sin querer) publiqué una versión más genérica de esta pregunta y que tiene algunas ideas adicionales sobre el problema: ¿La inyección de dependencia debe venir a expensas de encapsulación?

No está de acuerdo con el punto de que Spring rompe la encapsulación. Incluso si tiene pojo donde se ha expuesto y expuesto en clase y un tercero consume su jarra, aún existe la posibilidad de que el consumidor de jar haga lo mismo que es posible con la configuración de Spring bean. (cierto para cualquier otro idioma de OOP)

Spring simplemente proporciona una forma que se puede hacer a través del código y ese control se movió fuera del código (IOC).

Consumidor (considere que otro programador usa su biblioteca), crea un bean a través de la configuración de resorte, aún así su código tiene control. Ningún cuerpo lo detiene para validar la entrada dada por el usuario (el marco Spring IOC también pasa por el mismo código que otra clase llama a su setter) en setter.

public void setAge(int age) {
 if ( age < 0 ) {
   throw new AppException("invalid age!");
 }
 this.age=age;
}

Y esa es otra razón por la que prefiero Guice;) Tanto Guice como Spring implementan la especificación JSR 330 DI pero con Guice puedo inyectar en mis campos de instancias privadas sin establecedores y realmente no me gusta la inyección de constructores, ya que me ha parecido más difícil refactorizarlos. También es mucho más tipeo por poco valor en mi humilde opinión.

más tarde, Decano

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top