java - Spring中的接口依赖注入
问题描述
我有一个MainHandler类:
@Component
class MainHandler {
//inject this
private Handler handler;
@Autowired
public MainHandler(Handler handler){
this.handler = handler;
}
public void action(String message){
//watch photo
if (message.equals("photo")){
handler.handle();
}
if(message.equals("audio")){
//play music
handler.handle();
}
if(message.equals("video")){
//play video
handler.handle();
}
}
并跟随其他带有接口的处理程序。
我可以仅通过接口类型处理程序向 Spring Boot 注入依赖项吗?
@Component
public interface Handler {
void handle();
}
@Component
class PhotoHandler implements Handler {
public void handle(){
System.out.println("Featuring photo...");
}
}
@Component
class VideoHandler implements Handler {
public void handle(){
System.out.println("Playing video...");
}
}
@Component
class AudioHandler implements Handler {
public void handle(){
System.out.println("Playing music...");
}
}
或者我想在下面尝试这样的事情。可能吗 ?
class MainHandler {
private VideoHandler videoHandler;
private AudioHandler audioHandler;
private PhotoHandler photoHandler;
@Autowired
public MainHandler(VideoHandler videoHandler,
AudioHandler audioHandler,
PhotoHandler photoHandler) {
this.videoHandler = videoHandler;
this.audioHandler = audioHandler;
this.photoHandler = photoHandler;
}
public void action(String message){
//watch photo
if (message.equals("photo")){
photoHandler.handle();
}
if(message.equals("audio")){
//play music
audioHandler.handle();
}
if(message.equals("video")){
//play video
videoHandler.handle();
}
}
}
因此,处理程序的类型取决于用户的消息。我不知道 Spring 如何选择在这种情况下使用哪个处理程序。有什么解决办法吗?
解决方案
这种情况可以有多种解决方案。
选项1
您可以稍微调整处理程序的设计。
例如你可以引入一个方法
boolean canHandle(String message);
因此每个处理程序都可以回答是否可以处理传递的消息。
然后,您可以将所有处理程序的列表注入到您的MainHandler
.
private List<Handler> handlers;
现在有了该列表,您可以通过消息调用每个处理程序:
public void action(String message) {
handlers.stream()
.filter(h -> h.canHandle(message))
.forEach(handler -> handler.handle());
}
完整示例:
@SpringBootApplication
public class SO62370917 {
public static void main(String[] args) {
SpringApplication.run(SO62370917.class, args);
}
@Component
static class MainHandler {
private final List<Handler> handlers;
MainHandler(List<Handler> handlers) {
this.handlers = handlers;
}
public void action(String message) {
handlers.stream()
.filter(h -> h.canHandle(message))
.forEach(Handler::handle);
}
}
@Bean
CommandLineRunner cmd(MainHandler mainHandler) {
return args -> {
mainHandler.action("video");
mainHandler.action("audio");
mainHandler.action("photo");
};
}
interface Handler {
void handle();
boolean canHandle(String message);
}
@Component
class PhotoHandler implements Handler {
public void handle(){
System.out.println("Featuring photo...");
}
@Override
public boolean canHandle(String message) {
return "photo".equals(message);
}
}
@Component
class VideoHandler implements Handler {
public void handle(){
System.out.println("Playing video...");
}
@Override
public boolean canHandle(String message) {
return "video".equals(message);
}
}
@Component
class AudioHandler implements Handler {
public void handle(){
System.out.println("Playing music...");
}
@Override
public boolean canHandle(String message) {
return "audio".equals(message);
}
}
}
选项#2
使用限定符。
您可以随意命名您的处理程序,然后将 a 注入Map<String, Handler>
到您的mainHandler
. 键是 bean 名称和值 - 实际的处理程序。Spring 会自动处理这个问题。
@SpringBootApplication
public class SO62370917 {
public static void main(String[] args) {
SpringApplication.run(SO62370917.class, args);
}
@Component
static class MainHandler {
private final Map<String, Handler> handlers;
MainHandler(Map<String, Handler> handlers) {
this.handlers = handlers;
}
public void action(String message) {
if (handlers.containsKey(message)) {
handlers.get(message).handle();
}
}
}
@Bean
CommandLineRunner cmd(MainHandler mainHandler) {
return args -> {
mainHandler.action("video");
mainHandler.action("audio");
mainHandler.action("photo");
};
}
interface Handler {
void handle();
}
@Component("photo")
class PhotoHandler implements Handler {
public void handle() {
System.out.println("Featuring photo...");
}
}
@Component("video")
class VideoHandler implements Handler {
public void handle() {
System.out.println("Playing video...");
}
}
@Component("audio")
class AudioHandler implements Handler {
public void handle() {
System.out.println("Playing music...");
}
}
}
输出:
2020-06-14 13:06:47.140 INFO 29447 --- [ main] com.example.demo.SO62370917 : Started SO62370917 in 1.356 seconds (JVM running for 1.795)
Playing video...
Playing music...
Featuring photo...
推荐阅读
- reactjs - React.js - 如何在没有道具钻孔的情况下将事件处理程序传递给深度嵌套的组件?
- excel - 搜索值并返回相邻单元格
- ruby-on-rails - 在 options_from_collection_for_select 中过滤一个集合
- c++ - 将 std::async 与 future 作为成员一起使用时出现死锁
- ruby-on-rails - 我收到一个寻找文件 /sw/js 的 GET 请求的 RoutingError
- node.js - 使用 AWS 部署 Node 时遇到问题
- c# - 在文本框中过滤winform中的listview
- c# - Google Reporting API V4 缺失值
- typescript - Jest 和 Typescript:构造函数 super () 上未涵盖的分支
- python - 愚蠢的问题:如何在以下情况下替换或去除python中的单引号