Java Spring引导组件扫描无法识别不同bean的限定符注释

Java 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

我注意到了一些奇怪的事情,比如在Spring boot中使用Bridge设计模式。为了克服类路径中有两个相同类型的bean的问题,我使用了限定符注释。但是,由于某些原因,如果不为组件扫描使用通配符,它将无法工作

Color.java

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
,并将相应的
颜色
和相应的
@限定符
。。。但是最后一个选项不符合
桥接模式
,因为类的爆炸。。。