Это одна из причин, по которой мне не нравится автоматическое подключение непосредственно к частному полю. Я хотел бы сделать это, внедрив BaseComponent через конструктор BaseController:
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";
}
}
Запросы к /thing / bar вернут bar, а запросы к чему-то / foo вернут foo.
Обратите внимание, чтоабстрактный BaseComponent
фактически не объявляется как какой-либо компонент Spring и не имеет каких-либо зависимостей, которые автоматически добавляются. Вместо этого подклассы являются компонентами, а зависимости связаны в свои конструкторы и передаются через super
до BaseComponent
. Конструкторы подкласса предоставляют место для аннотации @Qualifier
, чтобы указать, какой BaseComponent
вы хотите.
Теоретически мне не нравится объявлять два класса, которые идентичны, кроме аннотаций. Однако на практике я обнаружил, что иногда проще всего объявить классы для хранения аннотаций Spring. Это лучше, чем в прежние времена конфигурации XML.