Java Spring引导组件扫描无法识别不同bean的限定符注释
我注意到了一些奇怪的事情,比如在Spring boot中使用Bridge设计模式。为了克服类路径中有两个相同类型的bean的问题,我使用了限定符注释。但是,由于某些原因,如果不为组件扫描使用通配符,它将无法工作 Color.javaJava Spring引导组件扫描无法识别不同bean的限定符注释,java,spring,spring-boot,dependency-injection,Java,Spring,Spring Boot,Dependency Injection,我注意到了一些奇怪的事情,比如在Spring boot中使用Bridge设计模式。为了克服类路径中有两个相同类型的bean的问题,我使用了限定符注释。但是,由于某些原因,如果不为组件扫描使用通配符,它将无法工作 Color.java package com.example.bridge; public interface Color { String fill(); } Blue.java package com.example.bridge; import org.springfr
package com.example.bridge;
public interface Color {
String fill();
}
Blue.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";
}
}
Red.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";
}
}
Shape.java
package com.example.bridge;
public abstract class Shape {
protected Color color;
public Shape(Color color){
this.color = color;
}
abstract public String draw();
}
Square.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();
}
}
Triangle.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.*”
它可以工作,并且应用程序可以启动。从技术上讲,我不需要为基本包设置通配符,它应该递归地获取所有bean。另外,我不明白“com.example.bridge.*.
和com.example.*.
之间的区别是什么。您得到了这个错误,因为当spring加载应用程序上下文时,它发现Square
是一个Springbean,因此尝试注入颜色。当它发现2impl时,会生成一个错误
颜色的注入仅在控制器上工作,因为您限定了注入点->
@Autowired
@限定词(“红色”)
私人色彩红色代码>
在初始化Square
时,在控制器内部手动键入Shape Square=new Square(红色)
您不需要在方格
类型上使用@服务
更新
关于软件包扫描,这个com.example.bridge
和这个com.example.bridge.*
实际上是一样的。你说它有效。。。但是在方块中注入了哪种颜色?我在您的代码中没有看到任何主要或限定符…@CodeScale我已经添加了控制器部分。在这种情况下,它会像预期的那样返回红方块。我不明白为什么您在控制器中手动将square
定义为Springbean et init此类型Shape square=new square(红色)代码>像这样的Square
不需要是一个Springbean…实际上,手动初始化是我试图理解为什么会出现这个问题的一个遗留问题。否则,你是对的,在这种情况下不需要注射。不管对象是如何初始化的,只有当组件扫描将基本包引用为“com.example.bridge.*”刚刚更新了我的答案时,应用程序才会工作。但它不起作用是正常的,因为您在方形类型上没有@限定符
。。。这里不是组件扫描的问题。没错,“com.example.bridge”和“com.example.bridge.*”应该是一样的,但由于某种原因,在本例中,“com.example.bridge.*”只起作用。另外,关于错误,它实际上抱怨了接受一种颜色的正方形的构造函数。它抱怨有两个类型为Color的bean,在初始化Square时无法区分它们。你是说唯一的解决办法是手动初始化Square,而Square根本不能被注入吗?你有两种解决方案。。。。注入Square
,但必须在其中注入合格的颜色(红色或蓝色impl)。但我认为这并不是“GOF Bridge”模式的想法。或者在控制器中注入颜色并手动创建正方形。所以你可以用任何颜色创建正方形。最后一个选项是创建类RedSquare
和BlueSquare
,并将相应的颜色
和相应的@限定符
。。。但是最后一个选项不符合桥接模式
,因为类的爆炸。。。