242 votes

Spring @Autowire sur les propriétés et les constructeurs.

Donc, depuis que j'utilise Spring, si je devais écrire un service qui a des dépendances, je ferais ce qui suit :

@Component
public class SomeService {
     @Autowired private SomeOtherService someOtherService;
}

Je suis maintenant tombé sur un code qui utilise une autre convention pour atteindre le même objectif

@Component
public class SomeService {
    private final SomeOtherService someOtherService;

    @Autowired
    public SomeService(SomeOtherService someOtherService){
        this.someOtherService = someOtherService;
    }
}

Ces deux méthodes fonctionneront, je le comprends. Mais y a-t-il un avantage à utiliser l'option B ? Pour moi, cela crée plus de code dans la classe et le test unitaire. (Avoir à écrire le constructeur et ne pas pouvoir utiliser @InjectMocks)

Y a-t-il quelque chose qui m'échappe ? Le constructeur autowired fait-il autre chose que d'ajouter du code aux tests unitaires ? S'agit-il d'un moyen plus approprié de réaliser l'injection de dépendances ?

0 votes

1 votes

Lequel est Option A y Option B ?

8voto

Nather Webber Points 127

J'espère que je ne serai pas déclassé pour avoir exprimé mon opinion, mais pour moi l'option A reflète mieux la puissance de l'injection de dépendance de Spring, alors que dans l'option B vous couplez votre classe avec votre dépendance, En fait, vous ne pouvez pas instancier un objet sans passer ses dépendances depuis le constructeur. . L'injection de dépendances a été inventée pour éviter cela en implémentant l'inversion de contrôle, donc pour moi l'option B n'a aucun sens.

5voto

Autowired fournit un crochet pour ajouter du code personnalisé avant de l'enregistrer dans le conteneur Spring. Supposons que SomeService étend une autre classe nommée SuperSomeService et il a un constructeur qui prend un nom comme argument. Dans ce cas, Autowired fonctionne bien. De plus, si vous avez d'autres membres à initialiser, vous pouvez le faire dans le constructeur avant de retourner l'instance au conteneur de printemps.

public class SuperSomeService {
     private String name;
     public SuperSomeService(String name) {
         this.name = name;
     }
}

@Component
public class SomeService extends SuperSomeService {
    private final SomeOtherService someOtherService;
    private Map<String, String> props = null;

    @Autowired
    public SomeService(SomeOtherService someOtherService){
        SuperSomeService("SomeService")
        this.someOtherService = someOtherService;
        props = loadMap();
    }
}

1voto

Anwar Sir Points 116

Je préfère l'injection de construction, juste parce que Je peux marquer ma dépendance comme finale ce qui n'est pas possible lors de l'injection de propriétés en utilisant l'injection de propriétés.

vos dépendances doivent être finales, c'est-à-dire non modifiées par le programme.

0voto

igor.zh Points 26

Il y a peu de cas où @Autowired est préférable. L'une d'entre elles est la dépendance circulaire. Imaginez le scénario suivant :

@Service
public class EmployeeService {
    private final DepartmentService departmentService;

    public EmployeeService(DepartmentService departmentService) {
        this.departmentService = departmentService;
    }
}

y

@Service
public class DepartmentService {
    private final EmployeeService employeeService;

    public DepartmentService(EmployeeService employeeService) {
        this.employeeService = employeeService;
    }
}

Alors Spring Bean Factory lancera une exception de dépendance circulaire. Cela ne se produira pas si vous utilisez @Autowired dans les deux beans. Et cela est compréhensible : l'injection du constructeur se produit à un stade très précoce de l'initialisation de Spring Bean, en createBeanInstance de Bean Factory, tandis que @Autowired L'injection basée sur les données se fait bien plus tard, au stade du post-traitement, et est effectuée par les personnes suivantes AutowiredAnnotationBeanPostProcessor . La dépendance circulaire est assez courante dans les applications complexes de Spring Context, et il ne s'agit pas seulement de deux beans se référant l'un à l'autre, mais d'une chaîne complexe de plusieurs beans.

Un autre cas d'utilisation, où @Autowired est très utile, c'est l'auto-injection.

@Service
public class EmployeeService {

    @Autowired
    private EmployeeService self;

}

Cela peut être nécessaire pour invoquer un conseillé à l'intérieur d'un même haricot. L'auto-injection est également abordée aquí y aquí .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X