web-dev-qa-db-fra.com

Comment fonctionne l'auto-câblage au printemps?

Je suis un peu confus quant à la manière dont inversion du contrôle (IoC) fonctionne dans Spring.

Disons que j'ai une classe de service appelée UserServiceImpl qui implémente l'interface UserService.

Comment cela serait-il _@Autowired_?

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

Est-ce que je ferais juste ce qui suit?

_UserService userService = new UserServiceImpl();
_
467
Blankman

Premièrement, et le plus important, tous les beans Spring sont gérés: ils "vivent" dans un conteneur, appelé "contexte d'application".

Deuxièmement, chaque application a un point d’entrée dans ce contexte. Les applications Web ont un servlet, JSF utilise un el-resolver, etc. Il existe également un emplacement où le contexte de l'application est initialisé et où tous les beans sont configurés automatiquement. Dans les applications Web, cela peut être un écouteur de démarrage.

Le câblage automatique se produit 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 haricots, 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. - vous ne faites jamais new UserServiceImpl() - le conteneur trouve chaque point d'injection et y définit une instance.

Dans vos contrôleurs, vous n’avez que 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 le <context:component-scan> afin que les classes soient analysées pour les annotations @Controller, @Service, etc.
  • Le point d'entrée d'une application Spring-MVC est le DispatcherServlet, mais il vous est caché. Par conséquent, l'interaction directe et le démarrage du contexte de l'application ont lieu en arrière-plan.
  • UserServiceImpl devrait également être défini comme un haricot - en utilisant <bean id=".." class=".."> ou en utilisant l'annotation @Service. Comme ce sera le seul implémenteur de UserService, il sera injecté.
  • En plus de l'annotation @Autowired, Spring peut utiliser le câblage automatique configurable par XML. Dans ce cas, tous les champs dont le nom ou le type correspond à un bean existant reçoivent automatiquement un bean injecté. En fait, c'était l'idée de départ du câblage automatique: avoir des champs injectés avec des dépendances sans configuration. D'autres annotations telles que @Inject, @Resource peuvent également être utilisées.
656
Bozho

Cela dépend si vous avez utilisé la route des annotations ou la route de définition XML du bean.

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>

L'auto-câblage a lieu au démarrage de l'application. Ainsi, dans fooController, qui souhaite utiliser les arguments comme argument pour utiliser la classe UserServiceImpl, vous l'annoteriez comme suit:

public class FooController {

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

    // rest of class goes here
}

Lorsqu'il verra @Autowired, Spring recherchera une classe qui correspond à la propriété dans la variable applicationContext et l'injectera automatiquement. Si vous avez plus d'un bean UserService, vous devrez alors spécifier lequel, il convient d'utiliser.

Si vous procédez comme suit:

UserService service = new UserServiceImpl();

Il ne prendra le @Autowired que si vous le configurez vous-même.

63
Ben J

@Autowired est une annotation introduite dans Spring 2.5 et 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(););
    }
}
18
mohit bansal

Comment @Autowired fonctionne-t-il en interne?

Exemple:

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

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

Fichier .xml, il se ressemblera s'il n'utilise pas @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
}

Fichier .xml, il se ressemblera s'il n'utilise pas @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émonstration en direct ci-dessous

Comment @Autowired fonctionne en interne?

9
jeet singh parmar

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

@Service("userService")

Le conteneur Spring prendra en charge le cycle de vie de cette classe lors de son enregistrement en tant que service.

Ensuite, dans votre contrôleur, vous pouvez automatiquement le filer (instancier) et utiliser ses fonctionnalités:

@Autowired
UserService userService;
6
Jitender Chahar

Spring dependency inject vous aide à supprimer le couplage de vos classes. Au lieu de créer un objet comme ceci:

UserService userService = new UserServiceImpl();

Vous allez utiliser ceci après avoir introduit DI:

@Autowired
private UserService userService;

Pour ce faire, vous devez créer un bean de votre service dans votre fichier ServiceConfiguration. Après cela, vous devez importer cette classe ServiceConfiguration dans votre classe WebApplicationConfiguration afin de pouvoir acheminer automatiquement ce bean dans votre contrôleur de la manière suivante:

public class AccController {

    @Autowired
    private UserService userService;
} 

Vous pouvez trouver un exemple de POC basé sur la configuration Java ici .

3
AbdusSalam

Il y a 3 façons de créer une instance en utilisant @Autowired.

1. @Autowired sur Propriétés

L'annotation peut être utilisée directement sur les propriétés, éliminant ainsi le besoin de getters et de 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 lorsque UserController est créé.

2. @Autowired sur les Setters

L'annotation @Autowired peut être utilisée avec les méthodes de définition. 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'occurrence de userService lorsque UserController est créé:

public class UserController {

    private UserService userService;

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

. @Autowired sur les constructeurs

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

public class UserController {

    private UserService userService;

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

Le concept entier d'inversion de contrôle signifie que vous êtes libre d'une corvée d'instancier manuellement des objets et de fournir toutes les dépendances nécessaires. Lorsque vous annotez une classe avec une annotation appropriée (par exemple, @Service), Spring instanciera automatiquement un objet pour vous. Si vous n'êtes pas familier avec les annotations, vous pouvez également utiliser un fichier XML. Toutefois, il n’est pas mauvais d’instancier manuellement les classes (avec le mot clé new] dans les tests unitaires lorsque vous ne souhaitez pas charger tout le contexte de ressort.

0
k13i

N'oubliez pas que vous devez activer l'annotation @Autowired en ajoutant l'élément <context:annotation-config/> dans le fichier de configuration de ressort. Ceci enregistrera la AutowiredAnnotationBeanPostProcessor qui prend en charge le traitement des annotations.

Et vous pouvez ensuite autoriser automatiquement votre service en utilisant la méthode d’injection sur site.

public class YourController{

 @Autowired
 private UserService userService; 

}

J'ai trouvé cela dans le message Spring @autowired annotation

0
David Pham