java - 工厂方法返回 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);
}
}
其他EventApprovedValidator和EventAccountingHqValidator实现类似。
从主代码我做这个电话
final EventUpdateValidatorStrategy validator = EventUpdateValidatorFactory.getValidator(event.getStatus());
validator.validate(user, eventSave.getMasterData(), event, eventSave.getExpenses(), eventSave.getSpeakers(), eventID);
结果是,当我进入EventSecondApprovalValidator时,所有自动装配的服务都为空,显然,我第一次使用该服务时收到了 NPE。
我如何根据EEventStatus正确使用工厂返回我需要的服务?
解决方案
在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");
}
推荐阅读
- android - 为 android 设置的值:为 editText 字段设置 maxLength 以避免 Android 中的 SQLInjection
- spring - 注入feign客户端
- aws-sdk - AWS 开发工具包与 AWS CLI - AWS Cloud Formation - Terraform
- django - 为什么我不能使用包含可为空外键的模型编写没有外键的数据记录?
- appannie - 用户帐户无权访问 App Annie Intelligence API
- apache-kafka - 无法创建 KSQL UDF jar
- ruby - Cocoon 不能在生产模式下工作,但所有 javascript 似乎都已正确加载
- c++ - 计算圆、椭圆的面积(动态方法)
- mysql - 从 Laravel 数据库中删除重复条目
- typescript - 如何为命名空间结构的模块编写类型声明