我有一个 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如何选择将在这种情况下使用的处理程序。有解决办法吗?
答案 0 :(得分:3)
您可以通过两种简单的方法进行操作:
@Qualifier
注入所需的特定bean。例如
@Component
class MainHandler {
@Autowired
@Qualifier("videoHandler") // example
private Handler handler;
public void action(){
handler.message(); // this will print playing video...
}
}
ApplicationContext
。例如:
@Component
class MainHandler {
@Autowired
private ApplicationContext context;
public void action(String message){
//watch photo
if (message.equals("photo")){
((PhotoHandler) context.getBean(PhotoHandler.class)).handle();
}
if(message.equals("audio")){
//play music
((AudioHandler) context.getBean(AudioHandler.class)).handle();
}
if(message.equals("video")){
//play video
((VideoHandler) context.getBean(VideoHandler.class)).handle();
}
}
}
答案 1 :(得分:1)
这种情况可以有多种解决方案。
选项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
使用限定词。
您可以根据自己的喜好命名处理程序,然后将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...