Comment Spring résout-il le problème de dépendance circulaire via le cache à trois niveaux ?

Table des matières

1. Qu'est-ce que le printemps

2. Problème de dépendance circulaire

Mécanisme de cache à trois niveaux

4. Comment résoudre le problème de dépendance circulaire via le cache à trois niveaux


 

1. Qu'est-ce que le printemps

Spring Framework est un framework de développement d'applications Java open source qui fournit un modèle de programmation complet et cohérent pour la création d'applications et de services au niveau de l'entreprise. Il a été créé par Rod Johnson en 2003 pour simplifier le développement Java et promouvoir le couplage lâche, la maintenabilité et l'extensibilité.

Les principales fonctionnalités du framework Spring incluent : 1. Inversion de contrôle (IoC) : la dépendance entre les objets est gérée via le conteneur IoC, ce qui réduit le couplage entre les composants et rend l'application plus flexible et plus testable. 2. Programmation orientée aspect (AOP) : grâce au module AOP, les préoccupations transversales (telles que la journalisation, la gestion des transactions, etc.) peuvent être séparées de la logique métier, ce qui rend le code plus modulaire et maintenable. 3. Accès aux données et intégration : Spring fournit un accès flexible aux données et une prise en charge de l'intégration, y compris la prise en charge des bases de données relationnelles, des bases de données NoSQL, des files d'attente de messages, des caches, etc. 4. Développement Web : le framework Spring fournit le module Spring MVC pour la création d'applications Web. Il est basé sur le modèle de conception MVC, qui offre une configuration flexible et la capacité de traiter les demandes. 5. Gestion des transactions : le framework Spring prend en charge la gestion déclarative des transactions, gère les limites des transactions et les règles de propagation via la configuration, et simplifie la programmation de la gestion des transactions. 6. Sécurité : le framework Spring fournit un ensemble de frameworks de sécurité pour la gestion de l'authentification et des autorisations afin de protéger la sécurité des applications. 7. Prise en charge des tests : le framework Spring fournit une prise en charge étendue des tests, y compris la prise en charge des tests unitaires, des tests d'intégration et des tests de bout en bout, ce qui permet aux développeurs d'écrire et d'exécuter plus facilement des scénarios de test.

Le concept de conception du framework Spring est léger, extensible et enfichable. Il est largement utilisé dans le développement Java au niveau de l'entreprise et est actuellement l'un des frameworks de développement Java les plus populaires.

 

2. Problème de dépendance circulaire

Le problème de dépendance circulaire de Spring fait référence au fait que lors de l'utilisation du conteneur IoC de Spring pour la création d'objets et l'injection de dépendances, s'il existe une dépendance circulaire, le processus de création d'objets peut ne pas être terminé ou des erreurs peuvent se produire.

La dépendance circulaire signifie que deux beans ou plus dépendent les uns des autres pour former une chaîne circulaire. Une dépendance circulaire se produit lorsque A dépend de B et B dépend de A.

Spring utilise un cache à trois niveaux (singletonFactories, earlySingletonObjects et singletonObjects) pour résoudre le problème lié aux dépendances circulaires. Le processus de résolution spécifique est le suivant :

  1. Tout d'abord, lorsqu'un bean est créé, Spring place le bean dans le cache singletonFactories.

  2. Si le Bean doit s'appuyer sur d'autres Beans pendant le processus de création, Spring créera les autres Beans requis via des appels récursifs.

  3. Lors de la création d'un autre bean, s'il s'avère que le bean est déjà dans le cache singletonFactories, cela signifie qu'une dépendance circulaire s'est produite.

  4. Dans ce cas, Spring essaiera d'obtenir une première instance du bean à partir du cache earlySingletonObjects, et s'il existe, renverra cette instance, sinon continuer à créer le bean.

  5. Si le problème de dépendance circulaire ne peut pas être résolu pendant le processus de création du bean, Spring lèvera une BeanCurrentlyInCreationException, indiquant que la création du bean ne peut pas être terminée.

Afin d'éviter les problèmes de dépendance circulaire, les méthodes suivantes peuvent être envisagées :

  1. Injection via le constructeur : injectez des dépendances à l'aide de constructeurs au lieu d'utiliser des méthodes Setter.

  2. Utilisez l'annotation Lazy : utilisez l'annotation @Lazy pour retarder l'initialisation des beans afin d'éviter la création prématurée de beans circulairement dépendants.

  3. Utiliser l'injection de méthode Setter : remplacez l'injection de dépendance par l'injection de méthode Setter et utilisez l'annotation @Autowired.

  4. Utilisez l'annotation @PostConstruct : utilisez l'annotation @PostConstruct pour effectuer certaines opérations d'initialisation après la création du bean.

Il convient de noter que bien que Spring fournisse un mécanisme pour résoudre les dépendances circulaires, des dépendances circulaires excessives peuvent entraîner une dégradation des performances et une dégradation de la lisibilité du code. Par conséquent, lors de la conception d'applications, essayez d'éviter les dépendances circulaires.

 

Mécanisme de cache à trois niveaux

Le mécanisme de cache à trois niveaux de Spring est conçu pour résoudre le problème de dépendance circulaire. Lorsque vous utilisez le conteneur IoC de Spring pour créer des objets, trois niveaux de cache sont utilisés pour résoudre les dépendances circulaires.

  1. Cache singletonFactories : Lors de la création de l'objet, si une dépendance circulaire est trouvée, Spring placera le Bean en cours de création dans le cache singletonFactories. Stocké dans ce cache est le fournisseur de l'objet, qui est la fabrique utilisée pour créer le Bean.

  2. cache earlySingletonObjects : si, au cours du processus de création d'un bean, il s'avère que le bean dépendant est déjà dans le cache singletonFactories, indiquant qu'une dépendance circulaire s'est produite. À ce stade, Spring essaiera d'obtenir une première instance du Bean (pas encore complètement initialisée) à partir du cache earlySingletonObjects pour résoudre le problème de dépendance circulaire.

  3. Cache singletonObjects : si la première instance ne peut pas être obtenue à partir du cache earlySingletonObjects, Spring placera le bean dans le cache singletonObjects pour stocker le bean entièrement initialisé.

Le workflow du cache L3 est le suivant :

  1. Lorsqu'un bean est créé, le cache singletonFactories est d'abord vérifié. Si le bean en cours de création se trouve déjà dans le cache, une dépendance circulaire s'est produite.

  2. Dans le cas d'une dépendance circulaire, il essaiera d'obtenir une première instance à partir du cache earlySingletonObjects. Si la première instance est obtenue avec succès, il renverra l'instance, ce qui résout le problème de la dépendance circulaire.

  3. Si la première instance ne peut pas être obtenue à partir du cache earlySingletonObjects, cela signifie que la dépendance circulaire ne peut pas être résolue et Spring lèvera une BeanCurrentlyInCreationException.

  4. Si la dépendance circulaire est résolue, le bean continuera à terminer le processus de création et sera finalement placé dans le cache singletonObjects pour être utilisé par d'autres beans.

Grâce au mécanisme de cache à trois niveaux, Spring peut résoudre la plupart des problèmes de dépendance circulaire et assurer le bon déroulement de la création et de l'injection de Bean. Mais il convient de noter que trop de dépendances circulaires augmenteront la complexité et les performances du système. Par conséquent, lors de la conception d'applications, essayez d'éviter l'apparition de dépendances circulaires.

Voici un exemple de code Java simple qui illustre l'implémentation du mécanisme de mise en cache à trois niveaux de Spring :

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
@Scope("singleton")
public class BeanA {
    private BeanB beanB;
    @Autowired
    public BeanA(BeanB beanB) {
        this.beanB = beanB;
    }
    public void doSomething() {
        System.out.println("BeanA is doing something");
        beanB.doSomething();
    }
}
@Component
@Scope("singleton")
public class BeanB {
    private BeanA beanA;
    @Autowired
    public BeanB(BeanA beanA) {
        this.beanA = beanA;
    }
    public void doSomething() {
        System.out.println("BeanB is doing something");
        beanA.doSomething();
    }
}
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        BeanA beanA = context.getBean(BeanA.class);
        beanA.doSomething();
    }
}

 

Dans le code ci-dessus, BeanAet BeanBdépendent les uns des autres. Une fois BeanAcréé, cela dépend de BeanB. Une fois BeanBcréé, il dépend à son tour de BeanA. Dans MainApp, transmettez l'instance ApplicationContextobtenue BeanAet appelez doSomethingla méthode. Spring gérera automatiquement les dépendances circulaires, assurant une création et une injection réussies via un BeanAmécanisme de cache à trois niveaux BeanB.

Il convient de noter que la méthode de configuration basée sur les annotations est utilisée dans le code ci-dessus, et que le @Componentbean est enregistré dans le conteneur Spring via l'annotation, et @Autowiredque l'injection de dépendance est effectuée à l'aide de l'annotation. De plus, la portée du bean peut être @Scopespécifiée via annotations singleton, qui est la portée par défaut et la condition préalable pour que le mécanisme de cache à trois niveaux prenne effet.

4. Comment résoudre le problème de dépendance circulaire via le cache à trois niveaux

Les étapes spécifiques à Spring pour résoudre le problème de dépendance circulaire via le cache à trois niveaux sont les suivantes :

  1. Créez le bean A et placez le bean dans le cache singletonFactories.

  2. Lorsque la création du bean A constate qu'il doit s'appuyer sur le bean B, Spring vérifie d'abord s'il existe une instance du bean B dans le cache singletonObjects.

  3. S'il existe une instance du bean B dans le cache singletonObjects, cela signifie que le bean B a été créé et peut être directement injecté dans le bean A.

  4. S'il n'y a pas d'instance de Bean B dans le cache singletonObjects, Spring vérifiera s'il existe un fournisseur de Bean B dans le cache singletonFactories (c'est-à-dire la fabrique utilisée pour créer le Bean B).

  5. S'il existe un fournisseur de bean B dans le cache singletonFactories, cela signifie que le bean B est en cours de création, mais qu'il n'a pas encore été créé. À ce stade, Spring placera le bean A en cours de création dans le cache earlySingletonObjects, représentant une première instance du bean A.

  6. Spring continue de créer le bean B. Lorsque le bean B est créé, il sera placé dans le cache singletonObjects et une première instance du bean A sera obtenue à partir du cache earlySingletonObjects.

  7. Une fois le haricot A et le haricot B créés, Spring terminera l'injection du haricot A et injectera le haricot B dans le haricot A.

Grâce à un tel mécanisme de cache à trois niveaux, Spring peut résoudre le problème des dépendances circulaires. Lorsqu'une dépendance circulaire se produit, le cache earlySingletonObjects de la première instance agit comme un stockage temporaire, garantissant que les objets de la dépendance circulaire peuvent être correctement créés et injectés. Mais il convient de noter que trop de dépendances circulaires augmenteront la complexité et les performances du système. Par conséquent, lors de la conception d'applications, essayez d'éviter l'apparition de dépendances circulaires.

Je suppose que tu aimes

Origine blog.csdn.net/2301_77899321/article/details/132072298
conseillé
Classement