Ricerca…


Osservazioni

Il codice sorgente per le applicazioni software di grandi dimensioni è generalmente organizzato in più unità. La definizione di un'unità normalmente varia a seconda del linguaggio di programmazione utilizzato. Ad esempio, il codice scritto in un linguaggio di programmazione procedurale (come C) è organizzato in functions o procedures . Allo stesso modo, il codice in un linguaggio di programmazione orientato agli oggetti (come Java, Scala e C #) è organizzato in classes , interfaces e così via. Queste unità di organizzazione del codice possono essere pensate come singole unità che costituiscono l'applicazione software complessiva.

Quando le applicazioni hanno più unità, le interdipendenze tra quelle unità si verificano quando una unità deve usarne altre per completare la sua funzionalità. Le unità dipendenti possono essere pensate come consumers e le unità da cui dipendono come providers di funzionalità specifiche.

L'approccio di programmazione più semplice è che i consumatori possano controllare completamente il flusso di un'applicazione software decidendo quali provider dovrebbero essere istanziati, utilizzati e distrutti in quali punti dell'esecuzione complessiva dell'applicazione. Si dice che i consumatori abbiano il pieno controllo sui fornitori durante il flusso di esecuzione, che dependencies dai consumatori. Nel caso in cui i fornitori abbiano le proprie dipendenze, i consumatori potrebbero doversi preoccupare di come i provider dovrebbero essere inizializzati (e rilasciati), rendendo il flusso di controllo sempre più complicato con l'aumento del numero di unità nel software. Questo approccio aumenta anche l'accoppiamento tra le unità, rendendo sempre più difficile cambiare le unità individualmente senza preoccuparsi di rompere altre parti del software.

Inversion of Control (IoC) è un principio di progettazione che promuove l'outsourcing delle attività di controllo del flusso come la scoperta dell'unità, l'istanziazione e la distruzione in un framework indipendente da consumatori e fornitori. Il principio alla base di IoC è quello di disaccoppiare consumatori e fornitori, liberando le unità software dal doversi preoccupare di scoprire, istanziare e ripulire le proprie dipendenze e consentire alle unità di concentrarsi sulle proprie funzionalità. Questo disaccoppiamento aiuta a mantenere il software estensibile e manutenibile.

L'iniezione di dipendenza è una delle tecniche per implementare l'inversione del principio di controllo in base alla quale le istanze di dipendenze (fornitori) vengono iniettate in un'unità software (il consumatore) invece che il consumatore deve trovarle e renderle istantanee.

Il framework Spring contiene al suo interno un modulo di iniezione delle dipendenze che consente di iniettare i bean Spring-managed in altri bean gestiti da Spring come dipendenze.

Iniezione di una dipendenza manualmente tramite la configurazione XML

Considera le seguenti classi Java:

class Foo {
  private Bar bar;

  public void foo() {
    bar.baz();
  }
}

Come si può vedere, la classe Foo deve chiamare il metodo baz su un'istanza di un'altra classe Bar perché il suo metodo foo funzioni correttamente. Si dice che la Bar sia una dipendenza per Foo poiché Foo non può funzionare correttamente senza un'istanza Bar .

Iniezione del costruttore

Quando si utilizza la configurazione XML per il framework Spring per definire i bean gestiti da Spring, un bean di tipo Foo può essere configurato come segue:

<bean class="Foo">
  <constructor-arg>
    <bean class="Bar" />
  </constructor-arg>
</bean>

o, in alternativa (più dettagliato):

<bean id="bar" class="bar" />

<bean class="Foo">
  <constructor-arg ref="bar" />
</bean>

In entrambi i casi, il framework Spring crea prima un'istanza di Bar e la injects in un'istanza di Foo . Questo esempio presuppone che la classe Foo abbia un costruttore che possa prendere un'istanza Bar come parametro, ovvero:

class Foo {
  private Bar bar;

  public Foo(Bar bar) { this.bar = bar; }
}

Questo stile è noto come iniezione del costruttore perché la dipendenza (istanza Bar ) viene iniettata attraverso il costruttore della classe.

Iniezione di proprietà

Un'altra opzione per iniettare la dipendenza Bar in Foo è:

<bean class="Foo">
  <property name="bar">
    <bean class="Bar" />
  </property>
</bean>

o, in alternativa (più dettagliato):

<bean id="bar" class="bar" />

<bean class="Foo">
  <property name="bar" ref="bar" />
</bean>

Ciò richiede che la classe Foo abbia un metodo setter che accetta un'istanza Bar , come ad esempio:

class Foo {
  private Bar bar;

  public void setBar(Bar bar) { this.bar = bar; }
}

Iniezione di una dipendenza manualmente tramite la configurazione di Java

Gli stessi esempi mostrati sopra con la configurazione XML possono essere riscritti con la configurazione Java come segue.

Iniezione del costruttore

@Configuration
class AppConfig {
  @Bean
  public Bar bar() { return new Bar(); }

  @Bean
  public Foo foo() { return new Foo(bar()); }
}

Iniezione di proprietà

@Configuration
class AppConfig {
  @Bean
  public Bar bar() { return new Bar(); }

  @Bean
  public Foo foo() {
    Foo foo = new Foo();
    foo.setBar(bar());

    return foo;
  }
}

Autowiring una dipendenza attraverso la configurazione XML

Le dipendenze possono essere autowired quando si utilizza la funzione di scansione dei componenti del framework Spring. Perché l'autowiring funzioni, è necessario configurare la seguente configurazione XML:

<context:annotation-config/>
<context:component-scan base-package="[base package]"/>

dove, base-package è il pacchetto Java completo all'interno del quale Spring dovrebbe eseguire la scansione dei componenti.

Iniezione del costruttore

Le dipendenze possono essere iniettate tramite il costruttore della classe come segue:

@Component
class Bar { ... }

@Component
class Foo {
  private Bar bar;

  @Autowired
  public Foo(Bar bar) { this.bar = bar; }
}

Qui, @Autowired è un'annotazione specifica di Spring. Spring supporta anche JSR-299 per abilitare la portabilità delle applicazioni ad altri framework di injection dependance basati su Java. Ciò consente a @Autowired di essere sostituito con @Inject come:

@Component
class Foo {
  private Bar bar;

  @Inject
  public Foo(Bar bar) { this.bar = bar; }
}

Iniezione di proprietà

Le dipendenze possono anche essere iniettate usando i metodi setter come segue:

@Component
class Foo {
  private Bar bar;

  @Autowired
  public void setBar(Bar bar) { this.bar = bar; }
}

Iniezione sul campo

Autowiring consente anche di inizializzare i campi all'interno delle istanze di classe direttamente, come segue:

@Component
class Foo {
  @Autowired
  private Bar bar;
}

Per le versioni Spring 4.1+ è possibile utilizzare Opzionale per dipendenze opzionali.

@Component
class Foo {

    @Autowired
    private Optional<Bar> bar;
}

Lo stesso approccio può essere utilizzato per il costruttore DI.

@Component
class Foo {
    private Optional<Bar> bar;

    @Autowired
    Foo(Optional<Bar> bar) {
        this.bar = bar;
    }
}

Autowiring una dipendenza attraverso la configurazione di Java

L'iniezione del costruttore tramite la configurazione Java può anche utilizzare l'autowiring, come ad esempio:

@Configuration
class AppConfig {
  @Bean
  public Bar bar() { return new Bar(); }

  @Bean
  public Foo foo(Bar bar) { return new Foo(bar); }
}


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow