Весна: Чому ми автоматично підключаємо інтерфейс, а не реалізований клас?


142

Приклад

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

Може хтось мені це пояснить.

  • Як весна знає, який поліморфний тип використовувати.
  • Мені потрібно @Qualifierчи @Resource?
  • Чому ми автоматично підключаємо інтерфейс, а не реалізований клас?

10
Ви автоматично підключаєте інтерфейс, щоб ви могли з'єднати іншу реалізацію - це один із пунктів кодування інтерфейсу, а не клас.
Дейв Ньютон

Ви підключите іншу реалізацію; Я не розумію питання.
Дейв Ньютон

Якщо ми проводимо проводку в інтерфейсі, що відбувається, коли в класі Impl існує метод видимості за замовчуванням, до якого мені потрібен доступ? Я не можу додати цей метод заглушки до інтерфейсу, оскільки загальнодоступний інтерфейс не може містити модифікатор за замовчуванням.
jlewkovich

Можливий дублікат класу Spring Autowiring vs. інтерфейс?
OhadR

1
Я думаю, що зробити інтерфейс лише для однієї реалізації - це дурна практика, яка прийнята у світі java. Результат - багато коду для сміття, але всі раді, що дотримувались правил SOLID та OOP. Скористайтеся вогнем і киньте весну на смітник історії.
авголубєв

Відповіді:


224

Як весна знає, який поліморфний тип використовувати.

Поки існує лише одна реалізація інтерфейсу і ця реалізація анотована при @Componentвключеному скануванні компонента Spring, Spring Framework може з'ясувати пару (інтерфейс, реалізація). Якщо сканування компонентів не ввімкнено, вам доведеться чітко визначити бін у вашому застосунку-config.xml (або еквівалентному файлі конфігурації весни).

Чи потрібен мені @Qualifier або @Resource?

Після того, як у вас є кілька варіантів реалізації, вам потрібно кваліфікувати кожну з них і під час автоматичного проводки вам потрібно буде використовувати @Qualifierанотацію, щоб ввести правильну реалізацію разом з @Autowiredанотацією. Якщо ви використовуєте @Resource (J2EE семантика), то вам слід вказати ім'я квасолі, використовуючи nameатрибут цієї анотації.

Чому ми автоматично підключаємо інтерфейс, а не реалізований клас?

По-перше, завжди корисно кодувати інтерфейси взагалі. По-друге, у випадку весни, ви можете ввести будь-яку реалізацію під час виконання. Типовим випадком використання є ін'єкція макету на етапі тестування.

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 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.


@stackoverflow Редагування питання не мало б сенсу, у відповіді належить новий код. Інакше питання не має сенсу, бо воно б відповіло само собою.
Дейв Ньютон

Vikdor - будь ласка, дивіться редагування. Це правильний спосіб анотувати класи та об'єкт, що вводиться?
stackoverflow

1
@VictorDombrovsky Чи @Autowired @Qualifier("a1") a;дійсно?
Lucky

1
@Lucky Я помилився. Я мав на увазі@Autowired @Qualifier("a1") A a;
Віктор Домбровський,

1
Ви навіть можете використовувати @Profile в реалізації, щоб контролювати, яку реалізацію слід вводити для цього інтерфейсу за допомогою програмних аргументів або властивостей програми.
b15

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.