2009-03-09 4 views
14

Viniendo de un fondo de C++ tengo que dominar la complejidad del mundo de Java y sus marcos. Mirando el marco de primavera para DI estoy teniendo dificultades para creer que tengo que hacer que cada función setter que estará sujeto a DI pública. ¿No incumple ese requisito el principio de ocultación de la información ?¿La inyección de dependencia de Spring no rompe la ocultación de información?

Por supuesto, quiero que la primavera sea capaz de establecer algunas partes privadas de mis clases , pero ciertamente NO quiero que todas las clases de clientes puedan hacer lo mismo con .

¿Qué me falta aquí?

Respuesta

6

Si tiene código en las interfaces, solo necesita exponer a los instaladores en las implementaciones. Al inyectar las interfaces en otras partes del sistema, no pueden acceder a los detalles de implementación o al estado de los objetos.

+1

Esta respuesta implica que "codificación de interfaces" significa que cada clase debe implementar una interfaz separada. Esto no es lo que significa el principio, como se describe en el libro de GoF. En realidad, solo se aplica para casos en los que necesita, o ya tiene, dos tipos de objetos separados, uno para la abstracción (interfaz) y otro para una implementación de esa abstracción. –

+0

Creo que es probable que descubras que las clases que necesitan inyectarse entre sí en una aplicación común de Spring son ** clases de ** servicios, como 'Dao's, etc. He descubierto que un gran número de ellas podría posiblemente tenga implementaciones alternativas –

+1

Sí, cuando tiene implementaciones múltiples se aplica el principio "codificar a la interfaz, no la implementación". Pero decir cosas como "si codifica a las interfaces ..." sin un contexto claro es engañoso, y los desarrolladores menos experimentados pueden malinterpretarlo fácilmente.El uso excesivo de interfaces separadas causa un gran daño, IMO. –

15

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

+2

1 de inyección de constructor. Expresa las dependencias mucho más fuerte y elimina la necesidad de instaladores "divertidos" – flq

+0

constructor injection ++: Una vez que crea un objeto, debe estar listo para usar y en un estado consistente. – Kalecser

+2

No todas las propiedades pueden ser necesarias para el correcto funcionamiento de la clase. En ese caso, siempre los inyecté a través de setters –

5

Puede que tenga que hacer un setter, que informará el exterior de algunos de sus detalles internos, pero no es necesario hacer un getter. Así que está revelando información sobre, pero no demasiado; no es realmente útil para nada más que su propósito previsto.

Además, recomendaría usar anotaciones y @Autowired, en cuyo caso no es necesario crear un setter público.

+0

+1 - abogar por anotaciones siempre que sea posible es algo bueno. Estoy intentando saltar ahora mismo, pero es difícil romper ese hábito XML. – duffymo

3

Si utiliza 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 muelles DI revelan información que no debe ocultarse.

0

Supongo que es una compensación. Usted reduce las dependencias cableadas, pero potencialmente expone las agallas de su implementación. Con las abstracciones correctas, puede reducir eso también, pero luego aumenta la complejidad de la base de 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 el uso de la inyección de constructor lo ayude, porque es más conceptual.

Tendré que echar un vistazo a @Autowire, tho '.

TJ

1

que tenía básicamente la misma pregunta aquí:

Encapsulation in the age of frameworks

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

1

nunca utilizado @Autowired, que tienden a preferir el uso de parámetros en los constructores, pero a veces es difícil entender lo que significan los parámetros, especialmente si tiene muchos parámetros; en ese caso, prefiero usar el enfoque "Constructor" descrito en Java efectivo. El constructor recibe el objeto de compilación (que tiene definidores) y se construye con él. Los atributos inyectados de la clase son finales (inmutabilidad), la clase "Builder" 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 se necesitan setters para ser creado sólo para la primavera:

<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 
    } 
} 
0

No estuvo de acuerdo con el punto de que la primavera rompe la encapsulación. Incluso si tiene un pojo en el que tiene get y set expuesto en clase y un tercero consume su jar, aún hay posibilidades de que el consumidor de jar haga lo mismo, lo que es posible con la configuración de Spring Bean. (verdadero para cualquier otro lenguaje OOP)

El resorte solo 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 bean a través de la configuración del resorte, aún así su código tiene control. Ningún cuerpo te detiene para validar la entrada dada por el usuario (el marco IOC de primavera también pasa por el mismo código que se hace por otra clase llamando a tu setter) en setter.

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

Y esa es otra razón por la que prefiero Guice;) Tanto Guice y primavera implementan las especificaciones DI JSR 330 pero con Guice que pueden inyectar en mis campos de instancia privadas sin setter y realmente me gusta la inyección de constructor, ya que ha parecido más difícil de refactorizar También es mucho más tipeo por poco valor en mi humilde opinión.

después, Dean

Cuestiones relacionadas