553 votes

Comment fonctionne le câblage automatique à Spring ?

Je suis un peu confus quant à la façon dont les inversion du contrôle ( IoC ) fonctionne dans Spring .

Disons que j'ai une classe de service appelée UserServiceImpl qui met en œuvre UserService interface.

Comment cela pourrait-il être @Autowired ?

Et dans mon Controllers comment pourrais-je instantiate un instance de ce service ?

Est-ce que je ferais simplement ce qui suit ?

UserService userService = new UserServiceImpl();

4voto

AbdusSalam Points 111

L'injection de dépendances de Spring vous aide à supprimer le couplage de vos classes. Au lieu de créer un objet comme ceci :

UserService userService = new UserServiceImpl();

Vous l'utiliserez après avoir introduit le DI :

@Autowired
private UserService userService;

Pour cela, vous devez créer un bean de votre service dans votre fichier ServiceConfiguration dossier. Après cela, vous devez importer ce ServiceConfiguration à votre WebApplicationConfiguration afin que vous puissiez intégrer ce haricot dans votre contrôleur comme ceci :

public class AccController {

    @Autowired
    private UserService userService;
} 

Vous pouvez trouver un POC basé sur une configuration java ici exemple .

1voto

Mak Points 329

Vous pouvez créer une instance de trois manières différentes en utilisant les éléments suivants @Autowired .

1. @Autowired sur les propriétés

L'annotation peut être utilisée directement sur les propriétés, éliminant ainsi le besoin de getters et setters :

    @Component("userService")
    public class UserService {

        public String getName() {
            return "service name";
        }
    }

    @Component
    public class UserController {

        @Autowired
        UserService userService

    }

Dans l'exemple ci-dessus, Spring recherche et injecte userService cuando UserController est créé.

2. @Autowired sur les Setters

Le site @Autowired peut être utilisée sur les méthodes setter. Dans l'exemple ci-dessous, lorsque l'annotation est utilisée sur la méthode setter, la méthode setter est appelée avec l'instance de userService cuando UserController est créé :

public class UserController {

    private UserService userService;

    @Autowired
    public void setUserService(UserService userService) {
            this.userService = userService;
    }
}

3. @Autowired sur les constructeurs

Le site @Autowired peut également être utilisée sur les constructeurs. Dans l'exemple ci-dessous, lorsque l'annotation est utilisée sur un constructeur, une instance de userService est injecté en tant qu'argument du constructeur lorsque la fonction UserController est créé :

public class UserController {

    private UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService= userService;
    }
}

1voto

Pratik Gaurav Points 407

En d'autres termes, le câblage automatique, c'est-à-dire le fait de relier automatiquement des éléments, pose la question de savoir qui le fait et quel type de câblage. La réponse est : Le conteneur le fait et le type de câblage secondaire est supporté, les primitives doivent être faites manuellement.

Question : Comment savoir quel type de câblage ?

Réponse : Nous le définissons comme byType,byName,constructor.

Question : Existe-t-il un moyen de ne pas définir le type de câblage automatique ?

Réponse : Oui, c'est possible grâce à une annotation, @Autowired.

Question : Mais comment le système sait-il que je dois choisir ce type de données secondaires ?

Réponse : Vous fournirez ces données dans votre fichier spring.xml ou en utilisant les annotations sterotype à votre classe afin que le conteneur puisse lui-même créer les objets pour vous.

1voto

Michu93 Points 734

De manière standard :

@RestController
public class Main {
    UserService userService;

    public Main(){
        userService = new UserServiceImpl();
    }

    @GetMapping("/")
    public String index(){
        return userService.print("Example test");
    }
}

Interface de service aux utilisateurs :

public interface UserService {
    String print(String text);
}

Classe UserServiceImpl :

public class UserServiceImpl implements UserService {
    @Override
    public String print(String text) {
        return text + " UserServiceImpl";
    }
}

Sortie : Example test UserServiceImpl

C'est un excellent exemple de classes étroitement couplées, un mauvais exemple de conception et il y aura des problèmes avec les tests (PowerMockito est également mauvais).

Voyons maintenant l'injection de dépendances de SpringBoot, un bel exemple de couplage souple :

L'interface reste la même,

Classe principale :

@RestController
public class Main {
    UserService userService;

    @Autowired
    public Main(UserService userService){
        this.userService = userService;
    }

    @GetMapping("/")
    public String index(){
        return userService.print("Example test");
    }
}

Classe ServiceUserImpl :

@Component
public class UserServiceImpl implements UserService {
    @Override
    public String print(String text) {
        return text + " UserServiceImpl";
    }
}

Sortie : Example test UserServiceImpl

et maintenant il est facile d'écrire des tests :

@RunWith(MockitoJUnitRunner.class)
public class MainTest {
    @Mock
    UserService userService;

    @Test
    public void indexTest() {
        when(userService.print("Example test")).thenReturn("Example test UserServiceImpl");

        String result = new Main(userService).index();

        assertEquals(result, "Example test UserServiceImpl");
    }
}

J'ai montré @Autowired sur le constructeur mais elle peut aussi être utilisée sur le setter ou le champ.

0voto

k13i Points 811

Le concept d'inversion de contrôle signifie que vous êtes libéré de la corvée d'instancier manuellement les objets et de fournir toutes les dépendances nécessaires. Lorsque vous annotez une classe avec une annotation appropriée (par ex. @Service ) Spring va automatiquement instancier l'objet pour vous. Si vous n'êtes pas familier avec les annotations, vous pouvez également utiliser le fichier XML à la place. Cependant, ce n'est pas une mauvaise idée d'instancier les classes manuellement (avec la fonction new ) dans les tests unitaires lorsque vous ne voulez pas charger tout le contexte de Spring.

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