Solution de dépendance circulaire au printemps

dépendance circulaire

 Les dépendances circulaires sont l'un des problèmes courants dans le framework Spring. Les dépendances circulaires se produisent lorsque deux classes ou plus se réfèrent les unes aux autres. Dans ce cas, le framework Spring ne peut pas déterminer quelle classe doit être instanciée et initialisée en premier, provoquant une exception. Les solutions courantes incluent : l'injection de constructeur, l'injection de méthode setter, l'injection de méthode d'usine statique et l'utilisation de bibliothèques tierces .

Version utilisée cette fois :

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.0</version>
    <relativePath/>
</parent>

l'affaire

public interface ServiceA {
    
    
}

public interface ServiceB {
    
    
}

@Service
public class ServiceAImpl implements ServiceA {
    
    
    private ServiceB serviceB;

    public ServiceAImpl(ServiceB serviceB) {
    
    
        this.serviceB = serviceB;
    }
}

@Service
public class ServiceBImpl implements ServiceB {
    
    
    private ServiceA serviceA;

    public ServiceBImpl(ServiceA serviceA) {
    
    
        this.serviceA = serviceA;
    }
}

Insérer la description de l'image ici

Solution

1. Refonte

Lorsqu’il existe une dépendance circulaire, il est probable qu’il y ait un problème de conception et que les responsabilités ne soient pas bien séparées. Vous devez essayer de repenser correctement les composants afin que leur hiérarchie soit bien conçue et qu'il n'y ait pas besoin de dépendances circulaires.

Si un composant ne peut pas être repensé (il peut y avoir plusieurs raisons : code hérité, code qui a été testé et ne peut pas être modifié, pas assez de temps ou de ressources pour une refonte complète...), mais il existe des solutions de contournement pour résoudre le problème.

2.@Paresseux

 Un moyen simple de résoudre les dépendances circulaires de Spring consiste à utiliser le chargement différé sur un bean . Autrement dit : ce Bean n'a pas été totalement initialisé, il est en fait injecté dans un proxy, qui ne sera totalement initialisé que lors de sa première utilisation.

@Service
public class ServiceAImpl implements ServiceA {
    
    
    private ServiceB serviceB;

    public ServiceAImpl(@Lazy ServiceB serviceB) {
    
    
        this.serviceB = serviceB;
    }
}

3.Setter/injection sur le terrain

En termes simples, vous utilisez l'injection de setter (ou l'injection de champ) pour les beans que vous devez injecter, et non l'injection de constructeur. En créant un Bean de cette manière, ses dépendances ne sont pas réellement injectées à ce moment-là, elles ne le seront que lorsque vous en aurez besoin.

@Service
public class ServiceAImpl implements ServiceA {
    
    
    private ServiceB serviceB;

    @Autowired
    public void setServiceB(ServiceB serviceB) {
    
    
        this.serviceB = serviceB;
    }
}

SpringBoot 2.6.x ne recommande pas l'utilisation de dépendances circulaires. Le moyen le plus simple consiste à autoriser les références circulaires dans le fichier de configuration global. La valeur par défaut de cette propriété est false et l'instruction display est true, ce qui peut éviter les exceptions de référence circulaire de la console. quand le projet démarre.

spring:
  main:
    allow-circular-references: true

4.@PostConstruct

Une autre façon de rompre le cycle consiste à l'utiliser sur la propriété que vous souhaitez injecter (qui est un bean) @Autowired, à utiliser @PostConstructl'annotation sur une autre méthode et à définir la dépendance sur les autres méthodes de cette méthode.

@Service
public class ServiceAImpl implements ServiceA {
    
    
    @Autowired
    private ServiceB serviceB;

    @PostConstruct
    public void init() {
    
    
        System.out.println(serviceB);
        serviceB.setServiceA(this);
    }
}

@Service
public class ServiceBImpl implements ServiceB {
    
    
    private ServiceA serviceA;

    public void setServiceA(ServiceA serviceA) {
    
    
        System.out.println(serviceA);
        this.serviceA = serviceA;
    }
}

Résumer:

Chemin Dépendances Méthode d'injection Capacité à résoudre les dépendances circulaires
Première situation Interdépendance AB Tous utilisent la méthode setter capable
Cas 2 Interdépendance AB Les deux utilisent la méthode constructeur ne peut pas
Situation trois Interdépendance AB L'injection de B dans A utilise un setter et l'injection de A dans B utilise un constructeur. capable
Situation quatre Interdépendance AB L'injection de B dans A utilise le constructeur et l'injection de A dans B utilise le setter. ne peut pas
Situation cinq Interdépendance AB Injectez B dans A et utilisez-le @Autowired, injectez A dans B et utilisez @PostConstruct+ setter capable
Situation six Interdépendance AB Injecter B dans A utilise @PostConstruct+ setter, injecter A dans B utilise@Autowired capable

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43847283/article/details/132328210
conseillé
Classement