使用服务作为"Factory"返回不同的 Bean 实现



我想在我的Spring应用程序中使用这种类型的服务类作为"工厂"来返回DocumentProcessor的正确实现,以响应提供的枚举值。

我这样做是因为我想将每个处理器本身设置为一个组件,并利用自动布线,而不是在需要每个处理器时创建新实例。

我还没有真正在其他任何地方看到这样做 - 谁能告诉我这是否是一个坏主意?

所有"TypeXYZDocumentProcessor"类都是抽象的"DocumentProcessor"基类的扩展。

@Service
public class DocumentProcessorService {
  @Autowired
  TypeXDocumentProcessor typeXDocumentProcessor;
  @Autowired
  TypeYDocumentProcessor typeYDocumentProcessor;
  @Autowired
  TypeZDocumentProcessor typeZDocumentProcessor;
  public DocumentProcessor getDocumentProcessor(DocumentType docType) {
    switch (docType) {
      case TYPE_X:
        return typeXDocumentProcessor;
      case TYPE_Y:
        return typeYDocumentProcessor;
      case TYPE_Z:
        return typeZDocumentProcessor;
      default:
        return null;
    }
  }
}  
@Component
public class TypeXDocumentProcessor extends DocumentProcessor {
  ...
}
public abstract class DocumentProcessor {
  ...
}

这是我的主张,我使用接口而不是抽象类,但是如果你真的需要一个抽象类,你可以返回它。

@Service
public class DocumentProcessorService {
  @Autowired
  // you can add here for examlpe a @Qualifier("typeXDocumentProcessor"),
  // then name your variable whatever you want.
  DocumentProcessor typeXDocumentProcessor;
  @Autowired
  DocumentProcessor typeYDocumentProcessor;
  @Autowired
  DocumentProcessor typeZDocumentProcessor;
  public DocumentProcessor getDocumentProcessor(DocumentType docType) {
    switch (docType) {
      case TYPE_X:
        return typeXDocumentProcessor;
      case TYPE_Y:
        return typeYDocumentProcessor;
      case TYPE_Z:
        return typeZDocumentProcessor;
      default:
        return null;
    }
  }
}  
@Component
public class TypeXDocumentProcessor implements DocumentProcessor {
  ...
}
@Component
public class TypeYDocumentProcessor implements DocumentProcessor {
  ...
}
@Component
public class TypeZDocumentProcessor implements DocumentProcessor {
  ...
}
public interface class DocumentProcessor {
  ...
}
你也可以

做这样的事情。我已经修改了您的抽象类DocumentProcessor以包含文档类型。代码未经测试或编译。

这样,您可以继续引入更多处理器类型,而根本不接触处理器服务。

@Service
public class DocumentProcessorService {
  @Autowired
  List<DocumentProcessor> documentProcessors;
  public DocumentProcessor getDocumentProcessor(DocumentType docType) {
    return documentProcessors.stream().filter(e -> e.getDocType().equals(docType)).findFirst().get();
  }
}
@Component
public class TypeXDocumentProcessor extends DocumentProcessor {
  public TypeXDocumentProcessor() {
    super(TYPE_X);
  }
}
// More Types...
public abstract class DocumentProcessor {
  ...
  DocumentType docType; 
  public DocumentProcessor(DocumentType docType) {
    this.docType = docType;
  }
  DocumentType getDocType() {
    return docType;
  }
}

我建议以不同的方式解决这个问题。让我们用多角恋(未测试)替换switchif块:

public enum DocumentType {
    TYPE_X("typeXDocumentProcessor"),
    TYPE_y("typeYDocumentProcessor");
    private DocumentProcessor processor;
    private final String beanName;
    DocumentType (String beanName){
      this.beanName = beanName;
    }
    public String process(){
        return processor.process();
    }

    @Component
    public static class DocumentTypeInjector {
        @Autowired
        private ApplicationContext context;
        @PostConstruct
        public void postConstruct() {
            for (DocumentType dt : EnumSet.allOf(DocumentType.class))
               dt.processor = context.getBean(dt.beanName)
        }
    }
}

然后,您的服务根本不需要 getDocumentProcessor 方法。例如,您只需要一个process方法,调用当前枚举实例的process

最新更新