首页 > 解决方案 > 工厂方法返回 Spring 服务

问题描述

我想要一个返回服务的工厂类,我可以用它来做一些验证。我实现了这个类

public class EventUpdateValidatorFactory {

    public EventUpdateValidatorStrategy getValidator(EEventStatus eventStatus) {

        if (SECOND_APPROVAL.equals(eventStatus)) {
            return new EventSecondApprovalValidator();
        } else if (APPROVED.equals(eventStatus)) {
            return new EventApprovedValidator();
        } else if (ACCOUNTING_HQ.equals(eventStatus)) {
            return new EventAccountingHqValidator();
        }

        throw new IllegalArgumentException("Unknown status");
    }
}

接口EventUpdateValidatorStrategy是这样的

public interface EventUpdateValidatorStrategy {

    default <T extends EventUpdateValidatorStrategy> void validate(User user, EventMasterData masterData, Event event, List<EventExternalSystemExpenseSave> expenses,
            List<EventExternalSystemSpeakerSave> speakers, long eventId) {

        this.validateMasterData(masterData, event);
        this.validateSpeakers(speakers, eventId);
        this.validateExpenses(expenses, eventId);
        this.doUpdate(user, masterData, expenses, speakers, eventId);

    }

    void validateMasterData(EventMasterData masterData, Event event);
    void validateExpenses(List<EventExternalSystemExpenseSave> expenses, long eventId);
    void validateSpeakers(List<EventExternalSystemSpeakerSave> speakers, long eventId);
    void doUpdate(User user, EventMasterData masterData, List<EventExternalSystemExpenseSave> expenses, List<EventExternalSystemSpeakerSave> speakers, long eventId);

}

EventSecondApprovalValidator这个

@Service
@Transactional
public class EventSecondApprovalValidator implements EventUpdateValidatorStrategy {

    @Autowired
    private EventService eventService;

    @Autowired
    private ContextDateService contextDateService;

    @Autowired
    private EventExpenseService eventExpenseService;

    @Autowired
    private EventExternalSystemDAO eventExternalSystemDAO;

    @Override
    public void validateMasterData(LocalEventMasterData masterData, Event event) {
        // some logic
    }

    @Override
    public void validateExpenses(List<EventExternalSystemExpenseSave> expenses, long eventId) {
        // some logic
    }

    @Override
    public void validateSpeakers(List<EventExternalSystemSpeakerSave> speakers, long eventId) {
        // some logic
    }

    @Override
    public void doUpdate(User user, EventMasterData masterData, List<EventExternalSystemExpenseSave> expenses, List<EventExternalSystemSpeakerSave> speakers, long eventId) {
        ofNullable(expenses).ifPresent(expensesToSave -> expensesToSave.forEach(expense -> this.eventExternalSystemDAO.updateExpense(user, expense)));
        this.eventExternalSystemDAO.updateEvent(user, masterData, eventId);
    }

}

其他EventApprovedValidatorEventAccountingHqValidator实现类似。

从主代码我做这个电话

final EventUpdateValidatorStrategy validator = EventUpdateValidatorFactory.getValidator(event.getStatus());
        validator.validate(user, eventSave.getMasterData(), event, eventSave.getExpenses(), eventSave.getSpeakers(), eventID);

结果是,当我进入EventSecondApprovalValidator时,所有自动装配的服务都为空,显然,我第一次使用该服务时收到了 NPE。

我如何根据EEventStatus正确使用工厂返回我需要的服务?

标签: javaspringspring-bootfactory-patternfactory-method

解决方案


EventUpdateValidatorFactory.getValidator(EEventStatus)方法中,您需要从上下文中返回bean,而不是使用关键字EventSecondApprovalValidator创建新实例。new

该类EventSecondApprovalValidator@Service注释(并且假设只有一种这种类型),这种类型的实例ApplicationContext将由 Spring 添加到所有依赖项注入。因此,只需从上下文中获取并使用它。

一种快速的方法如下:

public EventUpdateValidatorStrategy getValidator(ApplicationContext context, 
        EEventStatus eventStatus) {

    if (SECOND_APPROVAL.equals(eventStatus)) {
        return context.getBean(EventSecondApprovalValidator.class);
    } else if (APPROVED.equals(eventStatus)) {
        return context.getBean(EventApprovedValidator.class);
    } else if (ACCOUNTING_HQ.equals(eventStatus)) {
        return context.getBean(EventAccountingHqValidator.class);
    }

    throw new IllegalArgumentException("Unknown status");
}

您还可以@Autowire将所有验证器放入EventUpdateValidatorFactory并返回@Autowired实例。这将保持getValidator方法的签名相同,但您必须创建EventUpdateValidatorFactory一个@Component-esque 类。

@Component
public class EventUpdateValidatorFactory {

    @Autowired
    EventSecondApprovalValidator a;

    @Autowired
    EventApprovedValidator b;

    @Autowired
    EventAccountingHqValidator c;

    public EventUpdateValidatorStrategy getValidator(EEventStatus eventStatus) {

        if (SECOND_APPROVAL.equals(eventStatus)) {
            return a;
        } else if (APPROVED.equals(eventStatus)) {
            return b;
        } else if (ACCOUNTING_HQ.equals(eventStatus)) {
            return c;
        }

        throw new IllegalArgumentException("Unknown status");
    }

推荐阅读