Domanda

Proveniente da uno sfondo C ++, devo padroneggiare la complessità di Java mondo e le sue strutture. Guardando il quadro di primavera per DI I am trovando difficile credere che devo far funzionare ogni setter che sarà soggetto al pubblico DI. Questo requisito non infrange il principio di occultamento delle informazioni?

Ovviamente voglio che Spring sia in grado di impostare alcune parti private del mio classi, ma certamente NON voglio che ogni classe client sia in grado di fare lo stesso.

Cosa mi sto perdendo qui?

È stato utile?

Soluzione

Se si codifica interfacce , è necessario esporre solo setter sulle implementazioni. Quando si iniettano le interfacce in altre parti del sistema, non possono accedere ai dettagli di implementazione o allo stato degli oggetti.

Altri suggerimenti

Sono d'accordo con il tuo punto: ecco perché preferisco l'iniezione del costruttore.

Devi (potrebbe) dover creare un setter, che informerà l'esterno di alcuni dei tuoi dettagli interni, ma non è necessario fare un getter. Quindi stai rivelando alcune informazioni, ma non troppo; non è veramente utile per nient'altro che per lo scopo previsto.

Inoltre, consiglierei semplicemente di utilizzare le annotazioni e @Autowired, nel qual caso non è necessario creare un setter pubblico.

Se usi le annotazioni di primavera (@Autowired) puoi DI membri privati.

Se si sceglie accoppiamento lento e testabilità (unitaria) a mio avviso, le molle DI interrompono le informazioni che non devono essere nascoste.

Ho sostanzialmente avuto la stessa domanda qui:

Incapsulamento nell'era dei framework

Penso che la risposta potrebbe essere l'iniezione del costruttore. Esporre le tue proprietà con setter rende davvero difficile ecapsulare qualsiasi cosa e mantenere un buono stato dell'oggetto.

Mai usato @Autowired, tendo ad usare i parametri nei costruttori, ma a volte è difficile capire cosa significano i parametri, specialmente se hai molti parametri - in tal caso, preferisco usare il " Builder " approccio descritto in Java efficace. Il costruttore riceve l'oggetto build (che ha setter) e si costruisce con esso. Gli attributi iniettati della classe sono final (immutabilità), il " Builder " la classe contiene setter ma non getter (non è necessario poiché lo dichiariamo come classe interna della classe che viene costruita) e non è necessario creare setter solo per 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>

Codice classe:

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

Suppongo che sia un compromesso. Riducete le dipendenze cablate, ma potenzialmente esponete il fegato della vostra implementazione. Con le giuste astrazioni, puoi anche ridurlo, ma poi aumenti la complessità della base di codice (ad esempio, con una "connessione" generica che potrebbe essere una connessione LDAP o una connessione SQL).

Personalmente, non penso che usare l'iniezione del costruttore sia di aiuto, perché è più concettuale.

Dovrò dare un'occhiata a @Autowire, tho '.

tj

Volevo solo menzionare che ho (inavvertitamente) pubblicato una versione più generica di questa domanda e che ha ulteriori approfondimenti sul problema: L'iniezione di dipendenza deve andare a scapito dell'incapsulamento?

Non d'accordo con il punto che l'incapsulamento delle interruzioni primaverili. Anche se hai pojo dove sei stato esposto e esposto in classe e terze parti consumano il tuo vaso, è comunque probabile che il consumatore di vaso faccia lo stesso, come è possibile con la configurazione del bean Spring. (vero per qualsiasi altra lingua OOP)

Spring fornisce solo la strada che può essere fatta attraverso il codice e che il controllo è stato spostato fuori dal codice (IOC).

Consumatore (considera che altri programmatori usano la tua libreria), crea bean attraverso la configurazione di primavera, eppure il tuo codice ha il controllo. Nessun corpo ti impedisce di convalidare l'input fornito dall'utente (anche il framework IOC di primavera passa attraverso lo stesso codice che viene fatto da un'altra classe che chiama il tuo setter) in setter.

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

E questo è un altro motivo per cui preferisco Guice;) Sia Guice che Spring implementano le specifiche JSR 330 DI ma con Guice posso iniettare nei miei campi di istanze private senza setter e non mi piace molto l'iniezione del costruttore perché mi è sembrato più difficile rifattorizzare. È anche molto più digitante per non molto valore secondo la mia modesta opinione.

dopo, Dean

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top