SpringBoot-6-statemachine使用guard,action和@Ontransition
(2017-04-15 08:53:25)分类: 微服务 |
接前文http://blog.sina.com.cn/s/blog_7d1968e20102wvm7.html
如果我们想在状态机转换前进行判断,如果判断成功则进行跳转,否则可以跳转到其他状态,那么我们就需要guard的帮助。guard可以返回true或false,如果返回true那么就被actionListener监听进入action(如果定义了的话),再然后进入@WithstateMachine的@Ontransition注解的方法。guard返回false就不会进入指定状态,但在false之前可以指定进入其他状态
即流程如下:状态转变触发(trigger)->状态机启动并加载配置->guard->action->onTransition->变成新状态
下面就是例子:
@Override
public States
getName(){
return States.STATE1;
}
@Override
public
StateMachine<States, Events>
build(BeanFactory beanFactory) throws Exception{
StateMachineBuilder.Builder<States,
Events> builder =
StateMachineBuilder.builder();
builder.configureConfiguration().withConfiguration().machineId("state1").autoStartup(true).beanFactory(beanFactory);
builder.configureStates().withStates().initial(States.STATE1).states(EnumSet.allOf(States.class));
builder.configureTransitions().withExternal().source(States.STATE1).target(States.STATE2).event(Events.EVENT_A)
.guard(guardBuilder11To2()).action(actionBuilder11To2())
.and().withExternal().source(States.STATE2).target(States.STATE2).event(Events.EVENT_B);
return builder.build();
}
@Bean
public
Guard<States,
Events> guardBuilder11To2()
{
return new Guard<States,
Events>() {
@Override
public
boolean evaluate(StateContext<States,
Events> stateContext)
{
Student
student = stateContext.getExtendedState().get(Student.class,
Student.class);
if(student.getId() != 1)
{
System.out.println("builder1校验成功");
return true;
}
System.out.println("builder1校验不能跳转到2");
return
false;
}
};
}
@Bean
public
Action<States,
Events> actionBuilder11To2()
{
return new Action<States,
Events>() {
@Override
public
void execute(StateContext<States,
Events> stateContext) {
System.out.println("builder2的action成功跳转到2");
}
};
}
@Resource(name =
"actionBuilder11To2")
private
Action<States, Events>
actionBuilder11To2;
@Override
public States
getName(){
return States.STATE2;
}
@Override
public
StateMachine<States, Events>
build(BeanFactory beanFactory) throws Exception{
StateMachineBuilder.Builder<States,
Events> builder =
StateMachineBuilder.builder();
builder.configureConfiguration().withConfiguration().machineId("state2").autoStartup(true).beanFactory(beanFactory);
builder.configureStates().withStates().initial(States.STATE2).states(EnumSet.allOf(States.class));
builder.configureTransitions().withExternal().source(States.STATE2).target(States.STATE3).event(Events.EVENT_B)
.guard(guardBuilder22To3()).action(actionBuilder11To2);
return builder.build();
}
@Bean
public
Guard<States, Events>
guardBuilder22To3() {
return new Guard<States,
Events>() {
@Override
public
boolean evaluate(StateContext<States,
Events> stateContext) {
Student student =
stateContext.getExtendedState().get(Student.class,
Student.class);
if(student.getId() == 1)
{
System.out.println("校验成功");
return true;
}
return false;
}
};
}
@Bean
public
Action<States, Events>
actionBuilder22To3() {
return new Action<States,
Events>() {
@Override
public
void execute(StateContext<States,
Events> stateContext) {
System.out.println("action成功跳转到3");
}
};
}
@Autowired
private BeanFactory
beanFactory;
@Autowired
private
List<Builder> builders;
private
Map<States, Builder>
statesStateMachineMap = new
ConcurrentHashMap<>();
public void run(States
state, Events event) throws Exception{
Builder builder =
statesStateMachineMap.get(state);
StateMachine<States,
Events> stateMachine =
builder.build(beanFactory);
stateMachine.sendEvent(event);
}
public
StateMachine<States,
Events> create(States
state) throws Exception{
Builder builder =
statesStateMachineMap.get(state);
StateMachine<States,
Events> stateMachine =
builder.build(beanFactory);
stateMachine.getExtendedState().getVariables().put(Student.class,
new Student(1, "haha"));
return stateMachine;
}
@Override
public void
afterPropertiesSet() throws Exception {
statesStateMachineMap =
builders.stream().collect(Collectors.toMap(Builder::getName,
Function.identity()));
}
@OnTransition(target =
"STATE2")
public void
init(StateContext<States,
Events> context) {
Pupil s = new Pupil(12, "Bill", "piano");
System.out.println("Init to state1:" +
s.getName()+ ":" + s.getId() + ":" + s.getHobbies());
}
@OnTransition(target =
"STATE3", source = "STATE2")
public void
tansFrom2To3(StateContext<States,
Events> context) {
Student student =
context.getExtendedState().get(Student.class,
Student.class);
System.out.println("Transiform from 2 to 3 ," +
student.getId() + "---" + student.getName());
}
@WithStateMachine(name = "state1")
@OnTransition(target =
"STATE1")
public void init()
{
Pupil s = new Pupil(12, "Bill", "piano");
System.out.println("Init to state1:" +
s.getName()+ ":" + s.getId() + ":" + s.getHobbies());
}
@OnTransition(target =
"STATE2", source = "STATE1")
public void
tansFrom1To2() {
System.out.println("Transiform from 1 to
2");
}
@OnTransition(target =
"STATE3", source = "STATE2")
public void
tansFrom2To3() {
System.out.println("Transiform from 2 to
3");
}
@OnTransition(target =
"STATE2", source = "STATE2")
public void
tansFrom12o2() {
System.out.println("Transiform from 2 to
2");
}
1.在状态机配置中指定guard和action
1)Builder1。
关键:guard和action也可以定义成纯方法,而不是spring
bean。定义成bean的好处就是可以被其他Builder使用。
通过extendedState获取创建状态机时传递的参数:stateContext.getExtendedState().get(Student.class,
Student.class);
@Component
public class Builder1 implements Builder{
注意:
guard可以返回true或false,如果返回true那么就被actionListener监听进入action(如果定义了的话)guard返回false就不会跳转指定状态,但在false之前可以指定进入其他状态
}
2)Builder2。使用了builder1中的bean:actionBuilder11To2
@Component
public class Builder2 implements Builder{
// @Autowired
//
@Qualifier("actionBuilder11To2")
}
2.BuilderFactory:
提供了create方法,使用 stateMachine.getExtendedState().getVariables().put进行传递附加参数。
@Component
public class BuildFactory implements InitializingBean {
}
3.@WithStateMachine中的Ontransition中定义的方法
1)Builder2Transition
:方法中含有参数StateContext<States,
Events> context可以获取状态机传递的参数
@WithStateMachine(name = "state2")
public class Builder2Transition {
}
2)Builder1Transition
public class Builder1Transition {
}
4.测试
@Test
public void TestBuilder1() throws Exception{
StateMachine<States, Events>
machine1 = buildFactory.create(States.STATE1);
machine1.sendEvent(Events.EVENT_A);
StateMachine<States, Events>
machine2 = buildFactory.create(States.STATE2);
machine2.sendEvent(Events.EVENT_B);
}