[英]Spring boot component scan does not recognize qualifier annotation for different beans
在使用带有 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);
}
}
Controller:
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
好的,现在让我们将组件扫描的基础 package 更改为使用"com.example.*"
。 同样的问题。
现在,如果我将基础 package 更改为"com.example.bridge.*"
,它可以工作并且可以启动应用程序。 从技术上讲,我不需要为基础 package 设置通配符,它应该递归地获取所有 bean。 另外,我不明白"com.example.bridge.*"
和"com.example.*"
之间的区别是什么。
您收到此错误是因为当 spring 加载应用程序上下文时,它发现Square
是 spring bean,因此尝试注入颜色。 当它发现 2impl 时,它会产生一个错误。
颜色的注入仅适用于 controller 因为您限定了注入点 -> @Autowired @Qualifier("Red") private Color red;
当您在 controller 中手动初始化Square
类型时, Shape square = new Square(red);
您不需要Square
类型的@Service
更新
关于包扫描这个com.example.bridge
和这个com.example.bridge.**
实际上是相同的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.