无法使用 Spring Boot 框架区分 Bridge 设计模式中的可注入对象

Posted

技术标签:

【中文标题】无法使用 Spring Boot 框架区分 Bridge 设计模式中的可注入对象【英文标题】:Not able to distinguish injectable objects in the Bridge design pattern with Spring boot framework 【发布时间】:2020-08-11 17:27:24 【问题描述】:

我不确定如何在 Spring 的桥接设计模式中注入抽象类及其扩展。让我们考虑一下形状的经典桥梁设计模式示例:

颜色.java

public interface Color 

  String fill();

Blue.java

@Service("Blue")
public class Blue implements Color 
  @Override
  public String fill() 
    return "Color is Blue";
  

Red.java

@Service("Red")
public class Red implements Color 
  @Override
  public String fill() 
    return "Color is Red";
  

Shape.java

public abstract class Shape 
  protected Color color;

  @Autowired
  private Something something;

  @Value($foo.bar)
  private String fooBar;

  public Shape(Color color)
    this.color = color;
  

  abstract public String draw();

Square.java

public class Square extends Shape 

  public Square(Color color) 
    super(color);
  

  @Override
  public String draw() 
    return "Square drawn. " + color.fill();
  

三角形.java

public class Triangle extends Shape 

  public Triangle(Color color) 
    super(color);
  

  @Override
  public String draw() 
    return "Triangle drawn. " + color.fill();
  

BridgeApplication.java

@SpringBootApplication
public class BridgeApplication 
  public static void main(String[] args) 
    SpringApplication.run(BridgeApplication.class, args);
  

控制器:

@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();
  


当我们想要注入抽象类Shape 或其扩展如SquareTriangle 时,就会出现问题。由于构造函数接受一个 Color 对象,我们无法确定 ColorRed 还是 Blue (这就是这里使用 Bridge 设计模式的全部意义),所以我们不能定义 Shape 或将其扩展为 Spring Bean,因为将有多个 Color 类型的 bean 可用。简单的解决方法就像我直接构造对象而不是注入它所做的那样。但是,现在对于我要注入的任何值或我想在 Shape 类或其扩展(如 fooBarsomething)中注入的任何其他 Bean 将面临所有挑战,因为相应的类是手动构建的。

一种解决方案是开始处理手动注入,这会为 value 和 bean 注入带来很多不必要的复杂性,而且它根本不是一个干净的解决方案。喜欢this 或参考this question。所以我想知道是否有一种干净的方式可以在 Spring 框架中使用某种形式的 Bridge 设计模式,或者由于 Spring 的限制,没有。

【问题讨论】:

【参考方案1】:

你可以从ApplicationContext拿豆子.....但是你需要通过颜色拿豆子....

这是一个例子:

@RestController
public class BridgeController 

    private final Color red;
    private final Shape redSquareShape;

    public BridgeController(@Qualifier("Red") Color red,
                            ApplicationContext applicationContext) 
        this.red = red;
        this.redSquareShape = (Shape) applicationContext.getBean("square", red);
    

    @GetMapping("/red")
    @ResponseStatus(HttpStatus.OK)
    public String redSquare() 
        Shape square = new Square(red);
        return square.draw();
    


【讨论】:

我现在需要将 Shape 或 Square 定义为 bean 吗?一旦我将 Shape 定义为 bean,Shape 承包商就会产生歧义。 这里使用颜色构造函数创建形状。您也可以采取方形或三角形。在类型转换中给出它。从 applicationcontext 中,您可以通过传递 bean 名称来获取任何 bean 如果“square”指的是Square类,现在应该怎么做?我们是否也需要一个限定词? 第一个大写是小写字母,其余的都是一样的 我必须实际测试它,但我认为它不会解决整个问题,不过,我需要手动构造“Square”,这会导致注入“Something”时出现一些问题" 和 "fooBar" 因为我们不能为 "Square" 提供 bean

以上是关于无法使用 Spring Boot 框架区分 Bridge 设计模式中的可注入对象的主要内容,如果未能解决你的问题,请参考以下文章

spring boot使用profile来区分正式环境配置文件与测试环境配置文件

spring boot使用profile来区分正式环境配置文件与测试环境配置文件

使用带有 Spring Boot 的 Spock 测试框架来测试我的 REST 控制器

spring boot整合双持久层框架jpamybatis

spring-boot 速成 profile区分环境

在 Angular 5 应用程序中响应 Spring Boot 时无法读取授权标头