Essayons de le comprendre à travers les deux exemples.
Exemple 1
Auparavant, les applications utilisées pour générer des invites de commande acceptaient les entrées utilisateur les unes après les autres. Aujourd'hui, les infrastructures d'interface utilisateur instancient divers éléments d'interface utilisateur, parcourent divers événements de ces éléments (comme le survol de la souris, le clic, etc.) et les programmes utilisateur / principaux fournissent des points d'ancrage (par exemple, des écouteurs d'événements d'interface utilisateur en Java) pour écouter ces événements. Ainsi, le "contrôle" principal du flux d'éléments d'interface utilisateur est déplacé du programme utilisateur vers le cadre de l'interface utilisateur. Dans les premiers jours, c'était dans le programme utilisateur.
Exemple 2
Considérez la classe CustomerProcessor
ci - dessous:
class CustomerProcessor
{
SqlCustRepo custRepo = new SqlCustRepo();
private void processCustomers()
{
Customers[] custs = custRepo.getAllCusts();
}
}
Si je veux processCustomer()
être indépendant de toute implémentation de getAllCusts()
, pas seulement celle fournie par SqlCustRepo
, je devrai me débarrasser de la ligne: SqlCustRepo custRepo = new SqlCustRepo()
et la remplacer par quelque chose de plus générique, capable d'accepter différents types d'implémentations, de telle sorte que processCustomers()
cela fonctionnera simplement pour toute mise en œuvre fournie. Le code ci-dessus (instanciation de la classe requise SqlCustRepo
par la logique du programme principal) est une méthode traditionnelle et il n’atteint pas cet objectif de découplage processCustomers()
de la mise en œuvre de getAllCusts()
. En inversion de contrôle, le conteneur instancie la classe d'implémentation requise (spécifiée par, par exemple, configuration xml), l'injecte dans la logique de programme principale qui est liée selon les crochets spécifiés (par exemple, par @Autowired
annotation ou par getBean()
méthode dans le cadre Spring).
Permet de voir comment cela peut être fait. Considérez ci-dessous le code.
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");
}
}
Nous pouvons aussi avoir
class GraphCustRepo implements ICustRepo { ... }
et
<bean id="custRepo" class="GraphCustRepo">
et nous n'aurons pas besoin de changer App.java.
Au-dessus du conteneur (qui est le framework Spring), il incombe d'analyser le fichier xml, d'instancier le bean d'un type spécifique et de l'injecter dans le programme utilisateur. Le programme utilisateur n'a aucun contrôle sur la classe instanciée.
PS: IoC est un concept générique et est atteint à bien des égards. Les exemples ci-dessus y parviennent par injection de dépendance.
Référence: article de Martin Fowler .