有什么方法可以知道在 Spring 中使用来自父 class 的 bean 吗?
Is there any way to know in Spring what bean to use while being from the parent class?
我有这个特定问题,我无法使用 @Qualifier
,因为我需要父 class 中的 bean。我的想法是删除 baseComponent
属性并在 BaseController
中创建一个抽象方法,例如 getComponent()
和 return 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!");
}
}
您可以通过以下方式进行
import org.springframework.beans.factory.BeanFactory;
@RestController
public abstract class BaseController {
@Autowired
private BeanFactory beanFactory;
@GetMapping("/something")
public void doSomething() {
BaseComponent baseComponent = beanFactory.getBean("Foo", // or "Bar"
BaseComponent.class);
baseComponent.printSomething();
}
}
@Component("Foo")
public class FooComponent implements BaseComponent {
...
}
@Component("Bar")
public class BarComponent implements BaseComponent{
...
}
如果我没看错的话。
这是我不喜欢直接自动装配到私有字段的原因之一。我会通过 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 的请求将 return bar 而对 something/foo 的请求将 return foo.
请注意,抽象 BaseComponent
实际上并未声明为任何类型的 Spring 组件,也没有自动注入任何依赖项。相反,sub类 是组件,依赖项被连接到它们的构造函数中并通过 super
传递到 BaseComponent
。子类构造函数为 @Qualifier
注释提供了一个位置来指定您想要的 BaseComponent
。
理论上,我不喜欢声明两个 类 除了注释之外完全相同。但在实践中,我发现有时仅声明 类 来保存 Spring 注释是最简单的。这比以前的 XML 配置要好。
如果不想硬编码 bean 名称,可以使用泛型:
@RestController
public abstract class BaseController<T extends BaseComponent> {
@Autowired
private T baseComponent;
...
}
@RestController
public class FooController extends BaseController<FooComponent> {
...
}
我有这个特定问题,我无法使用 @Qualifier
,因为我需要父 class 中的 bean。我的想法是删除 baseComponent
属性并在 BaseController
中创建一个抽象方法,例如 getComponent()
和 return 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!");
}
}
您可以通过以下方式进行
import org.springframework.beans.factory.BeanFactory;
@RestController
public abstract class BaseController {
@Autowired
private BeanFactory beanFactory;
@GetMapping("/something")
public void doSomething() {
BaseComponent baseComponent = beanFactory.getBean("Foo", // or "Bar"
BaseComponent.class);
baseComponent.printSomething();
}
}
@Component("Foo")
public class FooComponent implements BaseComponent {
...
}
@Component("Bar")
public class BarComponent implements BaseComponent{
...
}
如果我没看错的话。
这是我不喜欢直接自动装配到私有字段的原因之一。我会通过 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 的请求将 return bar 而对 something/foo 的请求将 return foo.
请注意,抽象 BaseComponent
实际上并未声明为任何类型的 Spring 组件,也没有自动注入任何依赖项。相反,sub类 是组件,依赖项被连接到它们的构造函数中并通过 super
传递到 BaseComponent
。子类构造函数为 @Qualifier
注释提供了一个位置来指定您想要的 BaseComponent
。
理论上,我不喜欢声明两个 类 除了注释之外完全相同。但在实践中,我发现有时仅声明 类 来保存 Spring 注释是最简单的。这比以前的 XML 配置要好。
如果不想硬编码 bean 名称,可以使用泛型:
@RestController
public abstract class BaseController<T extends BaseComponent> {
@Autowired
private T baseComponent;
...
}
@RestController
public class FooController extends BaseController<FooComponent> {
...
}