我有一个特定的问题,我不能使用@Qualifier,因为我需要在父类中使用bean。我的想法是删除baseComponent属性,并在BaseController中创建一个抽象方法,例如getComponent()并为BaseComponent返回所需的bean ...但是也许有一种更干净的方法可以通过配置来实现。

@RestController
public abstract class BaseController {

    @Autowired
    private BaseComponent baseComponent;

    @GetMapping("/something")
    public void doSomething() {
        baseComponent.printSomething();
    }

}

@RestController
@RequestMapping(value = "/foo")
public class FooController extends BaseController {

}

@RestController
@RequestMapping(value = "/bar")
public class BarController extends BaseController {

}

public interface BaseComponent {
    void printSomething();
}

@Component
public class FooComponent implements BaseComponent {

    @Override
    public void printSomething() {
        System.out.println("foo!");
    }

}

@Component
public class BarComponent implements BaseComponent{

    @Override
    public void printSomething() {
        System.out.println("bar!");
    }

}

最佳答案

这是我不喜欢直接自动布线到私有字段的原因之一。我可以通过通过BaseController的构造函数注入BaseComponent来做到这一点:

public abstract class BaseController {

   private final BaseComponent baseComponent;

   protected BaseController(BaseComponent baseComponent){
       this.baseComponent = baseComponent;
   }

   @GetMapping("/something")
   public ResponseEntity<String> getSomething(){
       return new ResponseEntity<String>(baseComponent.getSomething(), HttpStatus.OK);
   }
}

@RestController
@RequestMapping("/foo")
public class FooController extends BaseController{

   @Autowired
   public FooController(@Qualifier("fooComponent") BaseComponent baseComponent) {
      super(baseComponent);
   }
}

@RestController
@RequestMapping("/bar")
public class BarController extends BaseController{

   @Autowired
   public BarController(@Qualifier("barComponent") BaseComponent baseComponent){
       super(baseComponent);
   }
}

@Component
public class BarComponent implements BaseComponent {

   @Override
   public String getSomething() {
       return "bar";
   }
}

@Component
public class FooComponent implements BaseComponent {

   @Override
   public String getSomething() {
     return "foo";
   }
}


对/ something / bar的请求将返回bar,而对something / foo的请求将返回foo。

注意,抽象BaseComponent实际上没有声明为任何类型的Spring组件,也没有自动注入任何依赖项。而是将子类作为组件,并将依赖项连接到其构造函数中,并通过super传递给BaseComponent。子类构造函数为@Qualifier批注提供一个位置,以指定所需的BaseComponent

从理论上讲,我不喜欢声明两个与注解相同的类。但是,在实践中,我发现有时仅声明类来保存Spring批注是最简单的。这比过去的XML配置要好。

09-05 11:21