Szukaj…


Uwagi

Kod źródłowy dla dużych aplikacji jest zazwyczaj podzielony na wiele jednostek. Definicja jednostki zwykle różni się w zależności od używanego języka programowania. Na przykład kod napisany w proceduralnym języku programowania (takim jak C) jest zorganizowany w functions lub procedures . Podobnie, kod w obiektowym języku programowania (takim jak Java, Scala i C #) jest zorganizowany w classes , interfaces i tak dalej. Te jednostki organizacji kodu można traktować jako pojedyncze jednostki tworzące całą aplikację.

Gdy aplikacje mają wiele jednostek, wzajemne zależności między tymi jednostkami pojawiają się, gdy jedna jednostka musi użyć innych, aby zakończyć swoją funkcjonalność. Jednostki zależne można traktować jako consumers a jednostki, od których są zależne, jako providers określonych funkcji.

Najłatwiejszym podejściem do programowania jest to, aby konsumenci mieli pełną kontrolę nad przepływem aplikacji, decydując, którzy dostawcy powinni zostać utworzeni, utworzeni i zniszczeni w jakich momentach ogólnej realizacji aplikacji. Mówi się, że konsumenci mają pełną kontrolę nad dostawcami podczas procesu wykonywania, które są dependencies dla konsumentów. W przypadku, gdy dostawcy mają swoje własne zależności, konsumenci mogą się martwić o to, w jaki sposób dostawcy powinni zostać zainicjowani (i zwolnieni), co czyni przepływ kontroli coraz bardziej skomplikowanym w miarę wzrostu liczby jednostek w oprogramowaniu. Takie podejście zwiększa również sprzężenie między jednostkami, co sprawia, że coraz trudniej jest zmieniać jednostki indywidualnie, nie martwiąc się o uszkodzenie innych części oprogramowania.

Inwersja kontroli (IoC) to zasada projektowania, która zaleca outsourcing działań związanych z kontrolą przepływu, takich jak wykrywanie jednostek, tworzenie instancji i niszczenie, w ramach niezależnych od konsumentów i dostawców. Podstawową zasadą stojącą za IoC jest oddzielenie konsumentów i dostawców, uwalniając jednostki oprogramowania od konieczności martwienia się o odkrywanie, tworzenie instancji i czyszczenie ich zależności oraz umożliwianie jednostkom skupienia się na własnej funkcjonalności. To oddzielenie pomaga utrzymać rozszerzalność i łatwość utrzymania oprogramowania.

Wstrzykiwanie zależności jest jedną z technik wdrażania zasady inwersji kontroli, w której przypadki zależności (dostawcy) są wstrzykiwane do jednostki oprogramowania (konsumenta) zamiast konieczności ich znajdowania i tworzenia przez użytkownika.

Struktura Spring zawiera moduł wstrzykiwania zależności w swoim rdzeniu, który umożliwia wstrzykiwanie fasoli zarządzanych przez Spring do innych fasoli zarządzanych przez Spring jako zależności.

Ręczne wstrzykiwanie zależności za pomocą konfiguracji XML

Rozważ następujące klasy Java:

class Foo {
  private Bar bar;

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

Jak można zobaczyć, klasa Foo musi wywołać metodę baz na instancji innej klasy Bar aby jej metoda foo działała pomyślnie. Mówi się, że Bar jest zależnością dla Foo ponieważ Foo nie może działać poprawnie bez instancji Bar .

Wtrysk konstruktora

Podczas korzystania z konfiguracji XML dla środowiska Spring do definiowania komponentów bean zarządzanych przez Spring, komponent bean typu Foo można skonfigurować w następujący sposób:

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

lub, alternatywnie (bardziej szczegółowe):

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

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

W obu przypadkach framework Spring najpierw tworzy instancję Bar i injects ją do instancji Foo . W tym przykładzie założono, że klasa Foo ma konstruktor, który może przyjąć instancję Bar jako parametr, to znaczy:

class Foo {
  private Bar bar;

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

Ten styl jest nazywany wstrzykiwaniem konstruktora, ponieważ do konstruktora klasy wstrzykuje się zależność (instancja Bar ).

Zastrzyk nieruchomości

Inną opcją wstrzyknięcia zależności Bar do Foo jest:

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

lub, alternatywnie (bardziej szczegółowe):

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

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

Wymaga to, aby klasa Foo miała metodę ustawiającą, która akceptuje instancję Bar , na przykład:

class Foo {
  private Bar bar;

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

Ręczne wstrzykiwanie zależności za pomocą konfiguracji Java

Te same przykłady, jak pokazano powyżej w konfiguracji XML, można ponownie zapisać w konfiguracji Java w następujący sposób.

Wtrysk konstruktora

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

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

Zastrzyk nieruchomości

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

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

    return foo;
  }
}

Automatyczne oparcie zależności poprzez konfigurację XML

Zależności można automatycznie rejestrować podczas korzystania z funkcji skanowania komponentów środowiska Spring. Aby automatyczne wiązanie działało, należy wykonać następującą konfigurację XML:

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

gdzie base-package to w pełni kwalifikowany pakiet Java, w ramach którego Spring powinien wykonać skanowanie komponentów.

Wtrysk konstruktora

Zależności można wstrzykiwać za pomocą konstruktora klasy w następujący sposób:

@Component
class Bar { ... }

@Component
class Foo {
  private Bar bar;

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

Tutaj @Autowired jest adnotacją dotyczącą wiosny. Spring obsługuje również JSR-299, aby umożliwić przenoszenie aplikacji do innych platform wstrzykiwania zależności opartych na Javie. Dzięki temu @Autowired można zastąpić @Inject jako:

@Component
class Foo {
  private Bar bar;

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

Zastrzyk nieruchomości

Zależności można również wstrzykiwać za pomocą metod ustawiających w następujący sposób:

@Component
class Foo {
  private Bar bar;

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

Iniekcja polowa

Automatyczne okablowanie pozwala również na bezpośrednie inicjowanie pól w instancjach klas w następujący sposób:

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

W wersjach wiosennych 4.1+ możesz użyć Opcjonalnej dla opcjonalnych zależności.

@Component
class Foo {

    @Autowired
    private Optional<Bar> bar;
}

To samo podejście można zastosować do konstruktora DI.

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

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

Automatyczne oparcie zależności poprzez konfigurację Java

Wstrzykiwanie konstruktora przez konfigurację Java może również wykorzystywać automatyczne okablowanie, takie jak:

@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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow