Я заметил кое-что странное на примере использования шаблона проектирования Bridge при загрузке Spring. Чтобы преодолеть проблемы с наличием двух bean-компонентов одного типа в пути к классам, я использую аннотацию Qualifier. Однако по какой-то причине он не работает без использования подстановочного знака для сканирования компонентов.
Цвет. 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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BridgeController {
@Autowired
@Qualifier("Red")
private Color red;
@GetMapping("/red")
@ResponseStatus(HttpStatus.OK)
public String redSquare() {
Shape square = new Square(red);
return square.draw();
}
}
Этот проект не запускается со следующим исключением:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-04-14 20:52:52.839 ERROR 9689 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.example.bridge.Square required a single bean, but 2 were found:
- Blue: defined in file [IdeaProjects/test-bridge-design/target/classes/com/example/bridge/Blue.class]
- Red: defined in file [IdeaProjects/test-bridge-design/target/classes/com/example/bridge/Red.class]
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Хорошо, теперь давайте изменим базовый пакет для сканирования компонентов, чтобы использовать "com.example.*"
. Та же проблема.
Теперь, если я изменю базовый пакет на "com.example.bridge.*"
, он будет работать, и приложение можно будет запустить. Технически, мне не нужно устанавливать подстановочный знак для базового пакета, и он должен рекурсивно собирать все компоненты. Кроме того, я не понимаю, в чем разница между "com.example.bridge.*"
и "com.example.*"
.