Spring 运行时使用交换 bean 类


@Component
@Qualifier("SUCCESS")
public class RandomServiceSuccess implements RandomService{
    public String doStuff(){
       return "success";
   }
}
@Component
@Qualifier("ERROR")
public class RandomServiceError implements RandomService{
    public String doStuff(){
       throw new Exception();
   }
}

调用代码

 @Controller
    public class RandomConroller {
        @Autowired 
        private RandomService service;
        public String do(){
           service.doStuff();
       }
    }

我在这里需要做的是根据可以从 http 请求中的某个自定义 http 标头检索的值来交换它们。谢谢!

我完全同意 Sotirios Delimanolis 的观点,即您需要注入所有实现并在运行时选择其中一个。

如果您有许多 RandomService 的实现,并且不想用选择逻辑弄乱RandomController,那么您可以让RandomService实现负责选择,如下所示:

public interface RandomService{
    public boolean supports(String headerValue);
    public String doStuff();
}
@Controller
public class RandomConroller {
    @Autowired List<RandomService> services;
    public String do(@RequestHeader("someHeader") String headerValue){
        for (RandomService service: services) {
            if (service.supports(headerValue)) {
                 return service.doStuff();
            }
        }
        throw new IllegalArgumentException("No suitable implementation");
    }
}

如果要为不同的实现定义优先级,可以使用Ordered并将注入的实现放入具有OrderComparatorTreeSet中。

限定符应该用于指定在为每个接口指定不同的 ID 后要在字段中注入的接口实例。按照@Soritios的建议,你可以做这样的事情:

@Component("SUCCESS")
public class RandomServiceSuccess implements RandomService{
    public String doStuff(){
       return "success";
   }
}
@Component("ERROR")
public class RandomServiceError implements RandomService{
    public String doStuff(){
       throw new Exception();
   }
}

@Component
public class MyBean{
    @Autowired
    @Qualifier("SUCCESS")
    private RandomService successService;
    @Autowired
    @Qualifier("ERROR")
    private RandomService successService;
    ....
    if(...)
}

。或者,您可以根据参数从应用程序上下文中仅获取所需的实例:

@Controller
public class RandomConroller {
    @Autowired
    private ApplicationContext applicationContext;
    public String do(){
        String myService = decideWhatSericeToInvokeBasedOnHttpParameter();
        // at this point myService should be either "ERROR" or "SUCCESS"
        RandomService myService = applicationContext.getBean(myService);
        service.doStuff();
   }
}

您可以同时注入两者并使用所需的一个。

@Inject
private RandomServiceSuccess success;
@Inject
private RandomServiceError error;
...
String value = request.getHeader("some header");
if (value == null || !value.equals("expected")) {
    error.doStuff();
} else {
    success.doStuff();
}

最新更新