Spring внедряет две реализации интерфейса для использования шаблона проектирования моста - PullRequest
0 голосов
/ 08 апреля 2020

Я реализовал образец шаблона проектирования моста в своем приложении, которое использует загрузку Spring. Мне было интересно, как мне удалось внедрить различные реализации интерфейса. Очевидно, что если я попытаюсь ввести их, он выдаст required a single bean, but 2 were found. Буду признателен, если вы поможете понять, как этого можно достичь в сочетании с внедрением зависимости:

Цвет. java

package com.example.bridge;

public interface Color {

  String fill();
}

Синий. java

package com.example.bridge;

import org.springframework.stereotype.Service;

@Service("Blue")
public class Blue implements Color {
  @Override
  public String fill() {
    return "Color is Blue";
  }
}

Красный. java

package com.example.bridge;

import org.springframework.stereotype.Service;

@Service("Red")
public class Red implements Color {
  @Override
  public String fill() {
    return "Color is Red";
  }
}

Форма. java

package com.example.bridge;

public abstract class Shape {
  protected Color color;

  public Shape(Color color){
    this.color = color;
  }

  abstract public String draw();
}

Квадрат. java

package com.example.bridge;

import org.springframework.stereotype.Service;

@Service
public class Square extends Shape {

  public Square(Color color) {
    super(color);
  }

  @Override
  public String draw() {
    return "Square drawn. " + color.fill();
  }
}

Треугольник. java

package com.example.bridge;

@Service
public class Triangle extends Shape {

  public Triangle(Color color) {
    super(color);
  }

  @Override
  public String draw() {
    return "Triangle drawn. " + color.fill();
  }
}

BridgeApplication. java

package com.example.bridge;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.example.bridge.*")
public class BridgeApplication {
  public static void main(String[] args) {
    SpringApplication.run(BridgeApplication.class, args);
  }
}

Проверьте это:

package com.example.bridge;

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class TestBridge {

  @Autowired
  @Qualifier("Red")
  private Red red;

  @Test
  public void testBridge() {
    //a square with red color
    Shape square = new Square(red);

    assertEquals(square.draw(), "Square drawn. Color is Red");
  }
}

ОБНОВЛЕНИЕ:

Во-первых, я заметил, что мне не хватало 'componentScan' для основного класса, и после его добавления теперь запускается приложение. Однако тот же подход не применим к тесту. Получил ли я компонентное сканирование или нет, вот что я получаю:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.bridge.Red' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=Red)}

Ответы [ 2 ]

1 голос
/ 08 апреля 2020

@Qualifier это решение. Пометьте component с помощью `@Qualifier (" unique-name "), и при внедрении компонента используйте этот квалификатор.

@Service("blue")
public class Blue implements Color {
    @Override
    public String fill() {
        return "Color is Blue";
    }
}

@Service("red")
public class Red implements Color {
    @Override
    public String fill() {
        return "Color is Red";
    }
}

При автоматическом подключении вы можете сделать следующее:

@Autowired
@Qualifier("red")
private Color red;

EDIT При внедрении конструктора выполните следующие действия:

@Autowired
public SomeClassConstructor(@Qualifier("red") Color red) {
    ...
}
0 голосов
/ 08 апреля 2020

Вы можете попробовать использовать аннотацию @Qualifier в своих сервисах. Затем в вашем @Autowired вы должны ссылаться на них с той же аннотацией.

https://docs.spring.io/spring/docs/4.3.12.RELEASE/spring-framework-reference/htmlsingle/#beans -autowired-annotation-qualifiers

@Service
@Qualifier("firstImplementation")
public class fistImplementation extends MyInterface {
 //doSomething
}

@Service
@Qualifier("secondImplementation")
public class secondImplementation extends MyInterface  { 
//doSomething
}


@Autowired
@Qualifier("firstImplementation") 
MyInterface myInterface;
...