Spring: Почему мы используем autwire интерфейс, а не реализованный класс?

Пример

interface IA
{
  public void someFunction();
}

@Resource(name="b")
class B implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someBfunc()
  {
     //doing b things
  }
}

@Resource(name="c")
class C implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someCfunc()
  {
     //doing C things
  }
}

class MyRunner
{

  @Autowire
  @Qualifier("b") 
  IA worker;

  worker.someFunction();
}

Может кто-нибудь объяснить это мне.

  • Как spring знает, какой полиморфный тип использовать.
  • Нужно ли мне @Qualifier или @Resource?
  • Почему мы используем autwire интерфейс, а не реализованный класс?

Ответ 1

Как spring знает, какой полиморфный тип использовать.

Пока существует только одна реализация интерфейса, и эта реализация аннотируется с @Component с включенным сканированием spring, инфраструктура spring может найти пару (интерфейс, реализация). Если проверка компонента не включена, вам необходимо явно определить bean в файле конфигурации приложения-config.xml(или эквивалентном spring).

Нужен ли мне @Qualifier или @Resource?

После того, как у вас есть несколько реализаций, вам необходимо квалифицировать каждый из них и во время автоматической проводки, вам нужно будет использовать аннотацию @Qualifier, чтобы ввести правильную реализацию вместе с аннотацией @Autowired. Если вы используете @Resource (семантика J2EE), тогда вы должны указать имя bean, используя атрибут name этой аннотации.

Почему мы используем autwire интерфейс, а не реализованный класс?

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

interface IA
{
  public void someFunction();
}


class B implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someBfunc()
  {
     //doing b things
  }
}


class C implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someCfunc()
  {
     //doing C things
  }
}

class MyRunner
{
     @Autowire
     @Qualifier("b") 
     IA worker;

     ....
     worker.someFunction();
}

Конфигурация bean должна выглядеть так:

<bean id="b" class="B" />
<bean id="c" class="C" />
<bean id="runner" class="MyRunner" />

В качестве альтернативы, если вы включили проверку компонентов в пакете, где они присутствуют, вы должны квалифицировать каждый класс с помощью @Component следующим образом:

interface IA
{
  public void someFunction();
}

@Component(value="b")
class B implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someBfunc()
  {
     //doing b things
  }
}


@Component(value="c")
class C implements IA
{
  public void someFunction()
  {
    //busy code block
  }
  public void someCfunc()
  {
     //doing C things
  }
}

@Component    
class MyRunner
{
     @Autowire
     @Qualifier("b") 
     IA worker;

     ....
     worker.someFunction();
}

Затем worker в MyRunner будет вводиться экземпляр типа B.

Ответ 3

Я думаю, что создание интерфейса только для одной реализации - глупая практика, принятая в мире Java. В результате получается много мусорного кода, но все рады, что они следовали правилам SOLID и OOP. Воспользуйтесь вывеской и бросьте весну в мусорное ведро истории.