propriété de spring @Autowire vs setter

Quelle est la différence entre anotate @Autowired à une propriété ou le faire dans le setter?

autant Que je sache, ils ont tous les deux le même résultat, mais il n'existe aucune raison d'utiliser l'un plutôt que l'autre?

mise à JOUR (pour être plus concis)

package com.tutorialspoint;

import org.springframework.beans.factory.annotation.Autowired;

public class TextEditor {
   private SpellChecker spellChecker;

   @Autowired
   public void setSpellChecker( SpellChecker spellChecker ){
      this.spellChecker = spellChecker;
   }

   public void spellCheck() {
      spellChecker.checkSpelling();
   }
}

et

package com.tutorialspoint;

import org.springframework.beans.factory.annotation.Autowired;

public class TextEditor {
   @Autowired
   private SpellChecker spellChecker;

   public TextEditor() {
      System.out.println("Inside TextEditor constructor." );
   }

   public void spellCheck(){
      spellChecker.checkSpelling();
   }
}
24
demandé sur luso 2015-11-06 11:46:26
la source

6 ответов

@Autowired annotation, vous n'avez pas besoin d'une méthode de définition. Une fois que le constructeur de votre bean est terminé avec l'allocation/création de l'objet, Spring va scanner cette annotation et injectera les instances d'objet que vous avez annoté.

tandis que si vous avez setter et si vous utilisez encore xml config, vous définirez explicitement les propriétés.

cela dit, Vous pouvez annoter votre méthode de constructeur et de setter avec une annotation auto-initialisée que je préférerais comme ceci plus tard, cela me donnerait de la flexibilité pour m'éloigner du printemps (bien que je ne le fasse pas).

17
répondu SMA 2015-11-06 11:49:47
la source

parfois vous avez besoin d'une instance de classe A, mais vous ne stockez pas A dans le champ de la classe. Vous avez juste besoin d'un pour effectuer une opération d'un coup. Ou, vous utilisez A pour obtenir une instance de B, et vous stockez B dans le champ.

dans ces cas, un setter (ou un constructeur) autowire vous conviendra mieux. Vous n'aurez pas de champs de niveau de classe inutilisés.

exemple Concret: Vous avez besoin de construire RabbitTemplate (un objet qui envoie des messages à RabbitMQ) De construire, vous avez besoin d' ConnectionFactory http://docs.spring.io/spring-amqp/docs/latest_ga/api/org/springframework/amqp/rabbit/core/RabbitTemplate.html#RabbitTemplate-org.springframework.amqp.rabbit.connection.ConnectionFactory-

Vous n'avez pas besoin de stocker ce ConnectionFactory. Dans ce cas, le code qui ressemble à ceci:

Class MyClass {
private RabbitTemplate template;

@Autowired 
void setConnectionFactory(ConnectionFactory c) {
    template=new RabbitTemplate(c);
}
}

...va vous servir mieux que directement l'autowiring le ConnectionFactory champ.

dans cet exemple, l'autowiring au niveau du constructeur serait encore mieux, parce que votre objet sera toujours complètement construit. Il est clair que ConnectionFactory est une dépendance obligatoire, pas facultative.

10
répondu Bartosz Bilicki 2017-10-24 22:19:27
la source

Si vous le pouvez, vous devriez éviter de l'incubateur. Si tu n'en as pas besoin, c'est mieux quand ça n'existe pas, non?

personnellement je préfère Guice me permettant d'écrire

public class TextEditor {
   private final SpellChecker spellChecker;

   @Inject public TextEditor(SpellChecker spellChecker) {
      this.spellChecker = spellChecker;
   }

   public void spellCheck(){
      spellChecker.checkSpelling();
   }
}

ceci va un peu plus loin: avec un final champ, je sais qu'il ne changera jamais, et j'ai l' multithreading visibilité garantie.

1
répondu maaartinus 2015-11-07 17:12:48
la source

Si vous utilisez @Autowired annotation sur un propriété, spring lancera la propriété en utilisant spring.XML. Vous n'avez pas besoin de setter dans ce cas.

Si vous utilisez @Autowired annotation sur un setter, vous spécifiez à spring qu'il devrait lancer cette propriété en utilisant cette méthode de setter où vous pouvez ajouter votre code personnalisé, comme initialiser une autre propriété avec ceci la propriété.

Utilisation avec par Exemple: Dans le cas de l'utilisation des opérations DAO en utilisant JdbcTemplate, vous avez besoin de DataSource comme entrée dans JdbcTemplate, mais DataSource n'est pas nécessaire comme propriété en soi. Ainsi, vous pouvez utiliser DataSource Setter pour initialiser JdbcTempate par l'auto-câblage DataSource Setter. Veuillez voir le code ci-dessous:

class DaoDemo{
   //@Autowired
   //private DataSource dataSource;
   private JdbcTemplate jdbcTemplate;

   @Autowired
   public void setDataSource(DataSource dataSource){
     //this.dataSource = dataSource;  
     this.jdbcTemplate = new JdbcTemplate(dataSource);
   }

   public int getTableRowCount(){
      String sql = "SELECT COUNT(*) FROM DEMOTABLE";
      //jdbcTemplate.setDataSource(dataSource);    //No need to do this as its done in DataSource Setter now.
      return jdbcTemplate.queryForObject(sql,Integer.class);

}

dans le code ci-dessus, la seule utilisation de dataSource était de passer dans JdbcTemplate. Donc, créer une propriété de dataSource n'a pas de sens ici. Donc, il suffit d'utiliser la méthode @Autowired on setter de la source de données bean pour obtenir son entrée à partir du printemps.xml et d'en faire usage à l'époque elle-même.

1
répondu Sahil Chhabra 2017-10-24 22:29:49
la source

Autowiring fonctionne mieux quand il est utilisé uniformément dans un projet. Si l'autowiring n'est pas utilisé en général, il pourrait être déroutant pour les développeurs de l'utiliser pour ne filer qu'une ou deux définitions de haricot. Avec @Autocâblés sur un champ que vous n'avez pas besoin d'une méthode de définition, qui d'une part rend la classe plus petite et plus facile à lire, mais d'autre part se moquer de la classe un peu plus laide.

les dépendances explicites dans la propriété et les paramètres du constructeur-arg ont toujours priorité sur l'autowiring. Vous ne peut pas autowire les soi-disant propriétés simples telles que les primitives, les chaînes, et les Classes (et les tableaux de telles propriétés simples). Cette limitation est de par sa conception.

Autowiring est moins précis que le câblage explicite. Spring est prudent pour éviter de deviner en cas d'ambiguïté qui pourrait avoir des résultats inattendus, les relations entre vos objets gérés par Spring ne sont plus explicitement documentés.

L'information de câblage peut ne pas être disponible pour les outils qui peuvent générer documentation d'un conteneur à ressort.

les définitions de fèves multiples dans le conteneur peuvent correspondre au type spécifié par la méthode de setter ou l'argument de constructeur à être auto-chauffé. Pour les tableaux, les collections ou les cartes, ce n'est pas nécessairement un problème. Toutefois, pour les dépendances qui s'attendent à une valeur unique, cette ambiguïté n'est pas arbitrairement résolue. Si aucune définition unique n'est disponible, une exception est lancée.

0
répondu Sarath Kumar Sivan 2015-11-06 12:00:29
la source

il y a un cas où l'utilisation de @Autowired sur une propriété optionnelle ne fonctionnerait pas.

si vous voulez faire une certaine initialisation en utilisant cette propriété, elle pourrait ne pas être définie avant que le constructeur soit appelé, et puisqu'elle est optionnelle, vous ne pouvez pas la mettre comme argument dans le constructeur.

dans ce cas, il est préférable d'utiliser une méthode de setter @Autowired, de sorte que vous puissiez effectuer l'initialisation une fois que la propriété est autowired.

0
répondu AdamSkwersky 2017-09-13 20:03:32
la source

Autres questions sur