繁体   English   中英

Spring 启动组件扫描无法识别不同 bean 的限定符注释

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM