使用Service作为“工厂”来返回不同的Bean实现

时间:2018-12-21 15:31:40

标签: java spring dependency-injection factory

我想在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 {
  ...
}

3 个答案:

答案 0 :(得分:2)

这是我的命题,我使用了Interface而不是抽象类,但是如果您确实需要抽象类,则可以在其上返回。

@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 {
  ...
}

答案 1 :(得分:1)

您也可以做这样的事情。我已经修改了您的抽象类DocumentProcessor以包括DocumentType。 代码未经测试或编译。

这样,您可以继续引入更多的处理器类型,而完全不涉及处理器服务。

@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;

  }
}

答案 2 :(得分:0)

我建议以另一种方式进行此操作。让我们用多态性(未经测试)替换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