Spróbujmy to zrozumieć na podstawie dwóch przykładów.
Przykład 1
We wcześniejszych czasach aplikacje generowały monity poleceń, aby akceptować dane wejściowe użytkownika jeden po drugim. Obecnie frameworki interfejsu użytkownika tworzą różne elementy interfejsu użytkownika, przechodzą przez różne zdarzenia tych elementów interfejsu użytkownika (takie jak najechanie myszą, kliknięcie itp.), A programy użytkownika / główne zapewniają przechwytywanie (na przykład detektory zdarzeń interfejsu użytkownika w Javie) do nasłuchiwania tych zdarzeń. Zatem „sterowanie” przepływem głównego elementu interfejsu użytkownika zostało przeniesione z programu użytkownika do środowiska interfejsu użytkownika. Wcześniej było w programie użytkownika.
Przykład 2
Rozważ klasę CustomerProcessor
poniżej:
class CustomerProcessor
{
SqlCustRepo custRepo = new SqlCustRepo();
private void processCustomers()
{
Customers[] custs = custRepo.getAllCusts();
}
}
Jeśli chcę processCustomer()
być niezależny od jakiejkolwiek implementacji getAllCusts()
, nie tylko tej dostarczonej przez SqlCustRepo
, będę musiał pozbyć się linii: SqlCustRepo custRepo = new SqlCustRepo()
i zastąpić ją czymś bardziej ogólnym, zdolnym do zaakceptowania różnego rodzaju implementacji, tak aby po processCustomers()
prostu działała dla wszelkie zapewnione wdrożenie. Powyższy kod (tworzenie instancji wymaganej klasy SqlCustRepo
według logiki programu głównego) jest tradycyjnym sposobem i nie osiąga celu oddzielenia processCustomers()
od implementacji getAllCusts()
. Podczas odwracania kontroli kontener tworzy instancję wymaganej klasy implementacji (określonej przez, powiedzmy konfigurację xml), wstrzykuje ją do logiki programu głównego, która zostaje powiązana według określonych haków (powiedzmy przez @Autowired
adnotację lub getBean()
metodę w ramach Spring).
Zobaczmy, jak to zrobić. Rozważ poniższy kod.
Config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="custRepo" class="JsonCustRepo" />
</beans>
CustRepo.java
interface ICustRepo
{ ... }
JsonCustRepo.java
class JsonCustRepo implements CustRepo
{ ... }
App.java
class App
{
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext("Config.xml");
ICustRepo custRepo = (JsonCustRepo) context.getBean("custRepo");
}
}
Możemy też mieć
class GraphCustRepo implements ICustRepo { ... }
i
<bean id="custRepo" class="GraphCustRepo">
i nie będziemy musieli zmieniać App.java.
Nad kontenerem (który jest strukturą sprężystą) odpowiada za skanowanie pliku xml, tworzenie instancji fasoli określonego typu i wstrzykiwanie jej do programu użytkownika. Program użytkownika nie ma kontroli nad tym, która klasa jest tworzona.
PS: IoC to ogólna koncepcja, którą można osiągnąć na wiele sposobów. Powyższe przykłady osiągają to poprzez wstrzyknięcie zależności.
Odniesienie: artykuł Martina Fowlera .