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();

751voto

Bozho Points 273663

Premièrement, et c'est le plus important, tous les Spring beans sont gérés - ils "vivent" à l'intérieur d'un conteneur, appelé "contexte d'application".

Ensuite, chaque application dispose d'un point d'entrée dans ce contexte. Les applications Web ont un Servlet, JSF utilise un el-resolver, etc. De plus, il y a un endroit où le contexte de l'application est bootstrapé et où tous les beans - autowired. Dans les applications web, cela peut être un listener de démarrage.

L'autocâblage se fait en plaçant une instance d'un bean dans le champ souhaité d'une instance d'un autre bean. Les deux classes doivent être des beans, c'est-à-dire qu'elles doivent être définies pour vivre dans le contexte de l'application.

Qu'est-ce que "vivre" dans le contexte de l'application ? Cela signifie que le contexte instancie les objets, pas vous. C'est-à-dire que vous ne faites jamais new UserServiceImpl() - le conteneur trouve chaque point d'injection et y place une instance.

Dans vos contrôleurs, vous avez juste ce qui suit :

@Controller // Defines that this class is a spring bean
@RequestMapping("/users")
public class SomeController {

    // Tells the application context to inject an instance of UserService here
    @Autowired
    private UserService userService;

    @RequestMapping("/login")
    public void login(@RequestParam("username") String username,
           @RequestParam("password") String password) {

        // The UserServiceImpl is already injected and you can use it
        userService.login(username, password);

    }
}

Quelques notes :

  • Dans votre applicationContext.xml vous devez activer l'option <context:component-scan> afin que les classes soient analysées pour le @Controller , @Service etc. annotations.
  • Le point d'entrée d'une application Spring-MVC est le DispatcherServlet, mais il vous est caché, et donc l'interaction directe et l'amorçage du contexte de l'application se font derrière la scène.
  • UserServiceImpl doivent également être définis comme des haricots, soit en utilisant la fonction <bean id=".." class=".."> ou en utilisant le @Service annotation. Puisqu'il sera le seul implémenteur de UserService il sera injecté.
  • En dehors de la @Autowired Spring peut utiliser un câblage automatique configurable en XML. Dans ce cas, tous les champs dont le nom ou le type correspond à un bean existant se voient automatiquement injecter un bean. En fait, c'était l'idée initiale de l'autowiring - avoir des champs injectés avec des dépendances sans aucune configuration. D'autres annotations comme @Inject , @Resource peut également être utilisé.

0 votes

Votre dernier point, donc dans l'implémentation de l'interface, UserServiceImpl, j'annote avec @Service correct ? Excellente réponse, elle a VRAIMENT clarifié les choses pour moi.

0 votes

L'interface est UserService userService ?

8 votes

Oui, UserServiceImpl est annoté avec Service, et UserService est l'interface

68voto

Ben J Points 2360

Cela dépend si vous voulez la route des annotations ou la route de la définition XML du haricot.

Supposons que vous ayez défini les haricots dans votre applicationContext.xml :

<beans ...>

    <bean id="userService" class="com.foo.UserServiceImpl"/>

    <bean id="fooController" class="com.foo.FooController"/>

</beans>

Le câblage automatique se fait au démarrage de l'application. Ainsi, dans fooController qui, pour des raisons de commodité, veut utiliser le UserServiceImpl vous l'annoterez comme suit :

public class FooController {

    // You could also annotate the setUserService method instead of this
    @Autowired
    private UserService userService;

    // rest of class goes here
}

Quand il voit @Autowired Spring cherchera une classe qui correspond à la propriété dans le fichier d'aide. applicationContext et l'injecter automatiquement. Si vous avez plus d'un UserService haricot, alors vous devrez qualifier celui qu'il doit utiliser.

Si vous faites ce qui suit :

UserService service = new UserServiceImpl();

Il ne captera pas le @Autowired sauf si vous le réglez vous-même.

2 votes

Alors, à quoi bon définir bean id sur applicationContext.xml . Nous devrons définir le userService variable avec UserService type. Alors pourquoi faire une entrée dans xml fichier.

21voto

mohit bansal Points 227

@Autowired est une annotation introduite dans Spring 2.5, et elle est utilisée uniquement pour l'injection.

Par exemple :

class A {

    private int id;

    // With setter and getter method
}

class B {

    private String name;

    @Autowired // Here we are injecting instance of Class A into class B so that you can use 'a' for accessing A's instance variables and methods.
    A a;

    // With setter and getter method

    public void showDetail() {
        System.out.println("Value of id form A class" + a.getId(););
    }
}

10voto

Comment @Autowired travailler en interne ?

Exemple :

class EnglishGreeting {
   private Greeting greeting;
   //setter and getter
}

class Greeting {
   private String message;
   //setter and getter
}

.xml, il aura la même apparence que si vous n'utilisez pas le fichier @Autowired :

<bean id="englishGreeting" class="com.bean.EnglishGreeting">
   <property name="greeting" ref="greeting"/>
</bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

Si vous utilisez @Autowired alors :

class EnglishGreeting {
   @Autowired //so automatically based on the name it will identify the bean and inject.
   private Greeting greeting;
   //setter and getter
}

.xml, il aura la même apparence que si vous n'utilisez pas le fichier @Autowired :

<bean id="englishGreeting" class="com.bean.EnglishGreeting"></bean>

<bean id="greeting" class="com.bean.Greeting">
   <property name="message" value="Hello World"/>
</bean>

Si vous avez encore des doutes, passez par la démo live ci-dessous.

Comment fonctionne @Autowired en interne ?

6voto

Jitender Chahar Points 184

Il vous suffit d'annoter votre classe de service UserServiceImpl avec annotation :

@Service("userService")

Le conteneur Spring s'occupera du cycle de vie de cette classe lorsqu'elle s'enregistrera comme service.

Ensuite, dans votre contrôleur, vous pouvez le câbler automatiquement (l'instancier) et utiliser sa fonctionnalité :

@Autowired
UserService userService;

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