英文:
Correct way of injecting a repository or service into Spring statemachine Action and Guard
问题
我一直在研究Spring Statemachine并使用它对订单的状态进行建模。我阅读了有关“Guards”和“Actions”的内容,并根据我们的需求提出了一个问题。
在Spring中,将`@Repository`或`@Service`注入到“Guard”或“Action”的正确方法是什么?
如[文档][1]中所述,可以通过声明一个`@Bean`来配置“Guard”和“Action”,但我没有看到通过这种方式注入`@Service`或`@Repository`的方法。
例如,以这个`EnumStateMachineConfigurerAdapter`为例:
@Configuration
@EnableStateMachineFactory
public class OrderStateMachineConfiguration extends EnumStateMachineConfigurerAdapter<OrderStates, OrderEvents> {
@Override
public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
states
.withStates()
.initial(OrderStates.PENDING)
.initial(OrderStates.APPROVED)
.initial(OrderStates.PAYMENT_REJECTED)
.end(OrderStates.DELIVERED)
.end(OrderStates.CANCELLED)
.end(OrderStates.INVALID)
.end(OrderStates.REFUNDED)
.end(OrderStates.ARCHIVED)
.states(EnumSet.allOf(OrderStates.class));
}
@Override
public void configure(StateMachineConfigurationConfigurer<OrderStates, OrderEvents> config) throws Exception {
config
.withConfiguration()
.listener(new StateMachineListener());
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
transitions
.withExternal().source(OrderStates.PENDING).target(OrderStates.APPROVED).event(OrderEvents.APPROVE).and()
...更多的转换
}
@Bean
public Guard<OrderStates, OrderEvents> orderIsConsistent() {
return ctx -> {
Order order = ctx.getExtendedState().get(ORDER_KEY, Order.class);
return order.getInconsistencies().isEmpty();
};
}
}
在顶部进行`@Autowired`似乎不太合适,因为这是一个`@Configuration`类,更不用说循环引用的风险了。
我想到的另一个解决方案是,在创建状态机时将所需的服务注入到“extendedState”或状态机头部,然后通过“StateContext”访问它?
如果文档中没有找到答案,我会非常感谢您提供一些见解。
[1]: https://docs.spring.io/spring-statemachine/docs/1.1.1.RELEASE/reference/htmlsingle/#configuring-guards
英文:
I've been getting into Spring Statemachine and modelling the state of an Order with it. I read about Guards
and Actions
, and based on our requirements, a question came up.
What is the correct way of injecting a Spring @Repository
or @Service
into a Guard
or Action
?
As described in the docs, Guard
s and Action
s are configured by declaring a @Bean
, but I see no way of injecting a @Service
or @Repository
this way.
For example, take this EnumStateMachineConfigurerAdapter
as an example:
@Configuration
@EnableStateMachineFactory
public class OrderStateMachineConfiguration extends EnumStateMachineConfigurerAdapter<OrderStates, OrderEvents> {
@Override
public void configure(StateMachineStateConfigurer<OrderStates, OrderEvents> states) throws Exception {
states
.withStates()
.initial(OrderStates.PENDING)
.initial(OrderStates.APPROVED)
.initial(OrderStates.PAYMENT_REJECTED)
.end(OrderStates.DELIVERED)
.end(OrderStates.CANCELLED)
.end(OrderStates.INVALID)
.end(OrderStates.REFUNDED)
.end(OrderStates.ARCHIVED)
.states(EnumSet.allOf(OrderStates.class));
}
@Override
public void configure(StateMachineConfigurationConfigurer<OrderStates, OrderEvents> config) throws Exception {
config
.withConfiguration()
.listener(new StateMachineListener());
}
@Override
public void configure(StateMachineTransitionConfigurer<OrderStates, OrderEvents> transitions) throws Exception {
transitions
.withExternal().source(OrderStates.PENDING).target(OrderStates.APPROVED).event(OrderEvents.APPROVE).and()
... more transitions
}
@Bean
public Guard<OrderStates, OrderEvents> orderIsConsistent() {
return ctx -> {
Order order = ctx.getExtendedState().get(ORDER_KEY, Order.class);
return order.getInconsistencies().isEmpty();
};
}
}
It doesn't seem right to @Autowired
a service on top because this is a @Configuration
class, not to mention the risk of circular references.
Another solution I came up with is maybe injecting the needed service into the extendedState
or a state machine header upon the creation of the state machine and then accessing it via the StateContext
?
I'd appreciate some insight on this because I couldn't find an answer in the docs.
答案1
得分: 2
您可以在方法级别上注入依赖项:
@Bean
@Autowired
public Guard<OrderStates, OrderEvents> orderIsConsistent(OrderService orderService) {
return ctx -> {
Long orderId = ctx.getExtendedState().get(ORDER_ID, Long.class);
Order order = orderService.findById(orderId);
return order.getInconsistencies().isEmpty();
};
}
英文:
You can inject dependencies on method level:
@Bean
@Autowired
public Guard<OrderStates, OrderEvents> orderIsConsistent(OrderService orderService) {
return ctx -> {
Long orderId = ctx.getExtendedState().get(ORDER_ID, Long.class);
Order order = orderService.findById(orderId);
return order.getInconsistencies().isEmpty();
};
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论