Spring свойство @Autowire vs setter

В чем разница между anotate @Autowired для свойства или сделать это в настройщике?

Насколько я знаю, оба они имеют одинаковый результат, но есть ли какая-то причина использовать их друг над другом?

UPDATE (чтобы быть более кратким)

Есть ли разница между этим

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

и этот

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

Ответы

Ответ 1

При аннотации @Autowired вам не нужен метод сеттера. После того, как ваш конструктор bean будет создан с назначением/созданием объекта, Spring сканирует эту аннотацию и будет вводить аннотации объектов, которые вы аннотировали.

Если у вас есть сеттер и если вы все еще используете xml config, вы явно задаете свойства.

Сказав это, вы могли бы аннотировать свой конструктор и метод setter с помощью автообновленной аннотации, которую я бы предпочел, поскольку это дало бы мне гибкость позже, чтобы отойти от Spring (хотя я этого не сделаю).

Ответ 2

Иногда вам нужен экземпляр класса A, но вы не храните A в поле класса. Вам просто нужен A для выполнения одноразовой операции. Или вы используете A для получения экземпляра B, и вы сохраняете B в поле.

В этих случаях автоустановщик сеттера (или конструктора) подойдет вам лучше. У вас не будет неиспользуемых полей уровня класса.

Конкретный пример: Вам нужно построить RabbitTemplate (объект, который отправляет сообщения в RabbitMQ) Чтобы построить его, вам понадобится 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-

Вам не нужно хранить этот ConnectionFactory. В этом случае код выглядит следующим образом:

Class MyClass {
private RabbitTemplate template;

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

... будет служить вам лучше, чем прямое автоподключение поля ConnectionFactory.

В этом примере автоустановка на уровне конструктора будет еще лучше, потому что ваш объект всегда будет полностью построен. Будет ясно, что ConnectionFactory является обязательной зависимостью, а не необязательной.

Ответ 3

Если вы можете, вы должны избегать установки. Если вам это не нужно, лучше, когда оно не существует, правильно?

Я лично предпочитаю, чтобы Guice позволял мне писать

public class TextEditor {
   private final SpellChecker spellChecker;

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

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

Это еще один шаг: в поле final я знаю, что он никогда не изменится, и я получаю многопоточность для видимости.

Ответ 4

Autowiring работает лучше всего, когда он последовательно используется в проекте. Если автоустановка вообще не используется, разработчикам может быть сложно использовать ее для подключения только одного или двух определений bean. С @Autowired на поле вам не нужен метод setter, который, с одной стороны, делает класс меньшим и более легким для чтения, но, с другой стороны, делает насмешливый класс немного уродливым.

Явные зависимости в настройках свойств и конструктора-arg всегда переопределяют автоподключение. Вы не можете autowire так называемые простые свойства, такие как примитивы, строки и классы (и массивы таких простых свойств). Это ограничение по умолчанию.

Autowiring менее точная, чем явная проводка. Spring старательно избегать угадывания в случае неоднозначности, которая может иметь неожиданные результаты, отношения между вашими объектами Spring уже не документируются явно.

Информация о подключении может быть недоступна для инструментов, которые могут генерировать документацию из контейнера Spring.

Несколько определений bean в контейнере могут соответствовать типу, указанному параметром setter или аргументом конструктора, который должен быть автообновлен. Для массивов, коллекций или карт это не обязательно проблема. Однако для зависимостей, которые ожидают одно значение, эта двусмысленность не разрешается произвольно. Если не существует уникального определения bean, генерируется исключение.

Ответ 5

Если вы используете аннотацию @Autowired для свойства , spring инициирует свойство с помощью spring.xml. В этом случае вам не нужен сеттер.

Если вы используете аннотацию @Autowired в сеттер, вы указываете spring, что она должна инициировать это свойство, используя этот метод setter, где вы можете добавить свой собственный код, например инициализировать какой-либо другой свойство с этим свойством.

Использование примера: В случае использования операций DAO с использованием JdbcTemplate вам нужен DataSource в качестве входа в JdbcTemplate, но DataSource не требуется как свойство самостоятельно. Таким образом, вы можете использовать DataSource Setter для инициализации JdbcTempate с помощью автоматической проводки DataSource Setter. Посмотрите приведенный ниже код:

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

}

В приведенном выше коде единственное использование dataSource должно было быть передано в JdbcTemplate. Таким образом, создание свойства dataSource здесь не имеет смысла. Поэтому просто используйте метод @Autowired on setter DataSource bean, чтобы получить его запись из spring.xml и использовать его в это конкретное время.

Ответ 6

Существует один случай, когда использование @Autowired в свойстве OPTIONAL не будет работать.

Если вы хотите выполнить некоторую инициализацию с использованием этого свойства, оно может не быть установлено до вызова конструктора, и поскольку оно является необязательным, вы не можете поместить его в качестве аргумента в конструктор.

В этом случае лучше использовать метод @Autowired setter, поэтому вы можете выполнить инициализацию после того, как свойство будет автоматически.