构建StateMachine

本文详细解析了 Spring StateMachine 的构建流程,包括 AnnotationBuilder 和 AnnotationConfigurer 的使用,以及状态机配置对象 StateMachineConfig 的创建过程。
摘要由CSDN通过智能技术生成

在上一篇《Spring Statemachine使用入门》中,我们使用过了StateMachineBuilder的内部类Builder创建了一个StateMachine对象,接下来我们具体来分析一下使用StateMachineBuilder.Builder创建状态机的具体过程。

StateMachineBuilder只有一个方法builder()并且没有任何成员变量,builder()方法返回一个StateMachineBuilder内部类Builder对象。

 

在Builder的构造方法中实例化了两个对象:StateMachineConfigBuilder和BuilderStateMachineConfigurerAdapter,而StateMachine的创建是在build()方法中。build()方法中用到了这两个对象,下面就先来看看StateMachineConfigBuilder,build()方法其余步骤后面再讲。

1、AnnotationBuilder:定义创建对象的方法

StateMachineConfigBuilder从类名可以猜出这是一个用来构造StateMachineConfig的辅助类,StateMachineConfigBuilder的顶级接口是AnnotationBuilder,这个接口只有一个方法用来构建并返回一个对象。

public interface AnnotationBuilder<O> {
   O build() throws Exception;
}

其实这个AnnotationBuilder接口有多个实现类,AnnotationBuilder的类结构体系是一个四层结构,底层有5个实现类,每个实现类类负责创建构造状态机对象的一类对象。如StateMachineModelBuilder用来构建ModelData对象的。

1.1、AbstractAnnotationBuilder:确保对象只创建一次

AbstractAnnotationBuilder是AnnotationBuilder的抽象实现类,这个抽象类实现了build()方法,通过对AtomicBoolean的cas操作确保doBuild()方法只被调用一次。

/** Flag tracking build */
private AtomicBoolean building = new AtomicBoolean();

/** Built object is stored here */
private O object;

@Override
public final O build() throws Exception {
   if(building.compareAndSet(false, true)) {
      object = doBuild();
      return object;
   }
   throw new IllegalStateException("This object has already been built");
}
protected abstract O doBuild() throws Exception;

1.2、AbstractConfiguredAnnotationBuilder:提供对自身进行配置的功能

AbstractConfiguredAnnotationBuilder提供了apply()方法使用接口AnnotationConfigurer实例对其进行配置的方式。这使得修改AnnotationBuilder成为一种策略,可以对其进行自定义。

public <C extends AnnotationConfigurer<O, B>> C apply(C configurer) throws Exception {
   add(configurer);
   return configurer;
}
private <C extends AnnotationConfigurer<O, B>> void add(C configurer) throws Exception {
   Assert.notNull(configurer, "configurer cannot be null");

   Class<? extends AnnotationConfigurer<O, B>> clazz =
         (Class<? extends AnnotationConfigurer<O, B>>) configurer.getClass();
   //如果当前构建状态在调用AnnotationConfigurer.configure()方法前
   if (!buildState.isConfigured()) {
      synchronized (mainConfigurers) {
         //允许有相同类型的多个AnnotationConfigurer则configurer直接追加到原有链表中
         //否则替换原有相同类型的AnnotationConfigurer,默认值为false
         List<AnnotationConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.mainConfigurers.get(clazz) : null;
         if (configs == null) {
            configs = new ArrayList<AnnotationConfigurer<O, B>>(1);
         }
         configs.add(configurer);
         this.mainConfigurers.put(clazz, configs);
         //如果在调用AnnotationConfigurer.init()时直接进行初始化方法调用
         if (buildState.isInitializing()) {
            configurer.init((B) this);
         }
      }
   } else {
      synchronized (postConfigurers) {
         List<AnnotationConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.postConfigurers.get(clazz) : null;
         if (configs == null) {
            configs = new ArrayList<AnnotationConfigurer<O, B>>(1);
         }
         configs.add(configurer);
         this.postConfigurers.put(clazz, configs);
         configurer.init((B) this);
      }
   }
}

上面这个apply方法接收一个AnnotationConfigurer类型的参数,然后通过add方法将这个configurer加入到链表mainConfigurers或postConfigurers中,至于加入到哪个链表中取决于apply()方法在哪个阶段配调用的。AbstractConfiguredAnnotationBuilder内部定义了一个枚举类,用来表示AnnotationBuilder构建对象的过程中所处于的状态,共有6种状态如下。!buildState.isConfigured()表示如果当前构建状态在CONFIGURING_MAINS之前就会将参数configurer表示的AnnotationConfigurer加入到mainConfigurers链表中否则加入到链表postConfigurers中。

buildState的状态流转发生在doBuild()方法,AbstractConfiguredAnnotationBuilder实现的doBuild()方法如下:

@Override
protected final O doBuild() throws Exception {
   synchronized (mainConfigurers) {
      buildState = BuildState.INITIALIZING_MAINS;
      beforeInit();            //空实现
      initMainConfigurers();   //调用mainConfigurers中的init(this)方法对自身进行初始化配置

      buildState = BuildState.CONFIGURING_MAINS;
      beforeConfigureMains();  //空实现
      configureMainConfigurers();//调用mainConfigurers中的configure(this)方法对自身进行配置

      buildState = BuildState.CONFIGURING_POSTS;
      beforeConfigurePosts();  //空实现
      configurePostConfigurers();//调用postConfigurers中的configure(this)方法对自身进行配置

      buildState = BuildState.BUILDING;
      O result = performBuild();//由具体子类实现

      buildState = BuildState.BUILT;
      return result;
   }
}

除了使用上面提到的apply()方法对 AnnotationBuilder进行配置外,AbstractConfiguredAnnotationBuilder还提供了一个重载方法用来配置自身。

public <C extends AnnotationConfigurerAdapter<O,I,B>> C apply(C configurer) throws Exception {
   add(configurer);
   configurer.addObjectPostProcessor(objectPostProcessor);
   //每个AnnotationConfigurerAdapter对象都持有当前配置的AnnotationBuilder对象的引用
   configurer.setBuilder((B) this);
   return configurer;
}

AnnotationConfigurerAdapter是AnnotationConfigurer的适配器实现,真对于配置不同的AnnotationBuilder的AnnotationConfigurer差异化实现都可通过集成AnnotationConfigurerAdapter然后实现差异化接口实现,如DefaultModelConfigurer:

AbstractConfiguredAnnotationBuilder最后留了一个抽象方法performBuild交由子类实现,这个方法就是最终创建对象的地方。

在分析子类实现的performBuild的方法之前先来看另一个相关的方法getSharedObject()方法:

public <C> C getSharedObject(Class<C> sharedType) {
   return (C) this.sharedObjects.get(sharedType);
}

sharedObjects是一个Map<Class<Object>, Object>类型的数据结构,通过调用setSharedObject方法填充元素,至于这个sharedObjects是存放什么数据的,下面介绍。

1.3、StateMachineConfigBuilder创建StateMachineConfig

AbstractConfiguredAnnotationBuilder的实现类共有5个,这里先分析StateMachineBuilder.Builder中的StateMachineConfigBuilder。

public class StateMachineConfigBuilder<S, E>
      extends
      AbstractConfiguredAnnotationBuilder<StateMachineConfig<S, E>, StateMachineConfigBuilder<S, E>, StateMachineConfigBuilder<S, E>> {

   @SuppressWarnings("unchecked")
   @Override
   protected StateMachineConfig<S, E> performBuild() throws Exception {
      // TODO: should prevent calling state/transition builder if model is given
      StateMachineModelBuilder<?, ?> modelBuilder = getSharedObject(StateMachineModelBuilder.class);
      StateMachineConfigurationBuilder<?, ?> configurationBuilder = getSharedObject(StateMachineConfigurationBuilder.class);
      StateMachineTransitionBuilder<?, ?> transitionBuilder = getSharedObject(StateMachineTransitionBuilder.class);
      StateMachineStateBuilder<?, ?> stateBuilder = getSharedObject(StateMachineStateBuilder.class);
      ModelData<S, E> model = (ModelData<S, E>) modelBuilder.build();
      ConfigurationData<S, E> stateMachineConfigurationConfig = null;
      stateMachineConfigurationConfig = (ConfigurationData<S, E>) configurationBuilder.build();
      transitionBuilder.setSharedObject(ConfigurationData.class, stateMachineConfigurationConfig);
      TransitionsData<S, E> transitions = (TransitionsData<S, E>) transitionBuilder.build();
      StatesData<S, E> states = (StatesData<S, E>) stateBuilder.build();
      return new StateMachineConfig<S, E>(stateMachineConfigurationConfig, transitions, states, model);
   }
}

在performBuild()方法中new了一个StateMachineConfig返回,而这个StateMachineConfig的几个构造参数都是通过调用父类方法getSharedObject()得到相应构造参数对象的builder对象,然后调用builder对象的build方法创建的对象。

默认sharedObjects内元素为空,那么什么时候往里填充数据的呢?

在Spring StateMachine中默认提供的类中,在这两个地方会调用StateMachineConfigBuilder的setSharedObject方法。

  • BuilderStateMachineConfigurerAdapter in StateMachineBuilder.init(StateMachineConfigBuilder)
  • AbstractStateMachineConfigurerAdapter.init(StateMachineConfigBuilder)

下面是上面第一个地方的实现:

BuilderStateMachineConfigurerAdapter() {
   try {
      getStateMachineModelBuilder();
      getStateMachineTransitionBuilder();
      getStateMachineStateBuilder();
      getStateMachineConfigurationBuilder();
   } catch (Exception e) {
      throw new StateMachineException("Error instantiating builder adapter", e);
   }
}

@Override
public void init(StateMachineConfigBuilder<S, E> config) throws Exception {
   config.setSharedObject(StateMachineModelBuilder.class, getStateMachineModelBuilder());
   config.setSharedObject(StateMachineTransitionBuilder.class, getStateMachineTransitionBuilder());
   config.setSharedObject(StateMachineStateBuilder.class, getStateMachineStateBuilder());
   config.setSharedObject(StateMachineConfigurationBuilder.class, getStateMachineConfigurationBuilder());
}

在构造方法中实例化了这四个builder对象,然后当在AnnotationBuilder的apply方法调用时触发BuilderStateMachineConfigurerAdapter的init方法为StateMachineConfigBuilder设置这四个builder对象。

下面是getStateMachineModelBuilder()的实现,其余三个一样。

protected final StateMachineModelBuilder<S, E> getStateMachineModelBuilder() throws Exception {
   if (modelBuilder != null) {
      return modelBuilder;
   }
   modelBuilder = new StateMachineModelBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
   configure(modelBuilder);//空实现
   return modelBuilder;
}

 2、AnnotationConfigurer:用来配置AnnotationBuilder

通过上面对接口AnnotationBuilder及其实现类StateMachineModelBuilder的源码走读了解到相应的AnnotationConfigurer实现类通过init和configure方法配置对应的AnnotationBuilder实现类。

所有AnnotationConfigurer首先调用其init(AnnotationBuilder)方法。调用所有init方法后,将调用每个configure(AnnotationBuilder)方法。

顶级接口AnnotationConfigurer定义了三个方法:

public interface AnnotationConfigurer<O, B extends AnnotationBuilder<O>> {

   /**
    * 初始化AnnotationBuilder。在这里,只应创建和修改共享状态,
    * 而不应在用于生成对象的AnnotationBuilder上创建和修改属性。
    * 这样可以确保configure方法在生成时使用正确的共享对象
    */
   void init(B builder) throws Exception;

   /**
    * 通过在AnnotationBuilder上设置必要的特性来配置AnnotationBuilder
    */
   void configure(B builder) throws Exception;

    /**
    * 是否可以用于配置这个builder
    */
   boolean isAssignable(AnnotationBuilder<O> builder);
}

上一节中我们已经看过了BuilderStateMachineConfigurerAdapter的实现了,下面我们来看一下其余实现类。

2.1、AnnotationConfigurerAdapter:AnnotationConfigurer的增强适配器

AnnotationConfigurerAdapter默认实现了AnnotationConfigurer的三个方法,并额外提供了几个方法增强自身功能。

builder的setter和getter方法:getter方法可以方便的获取配置的AnnotationBuilder,setter方法我们之前已经看到过了,这里在回顾一下如下图。

and方法:使用AnnotationConfigurer完成后返回AnnotationBuilder。这对于方法链接很有用。

public I and() {
   // we're either casting to itself or its interface
   return (I) getBuilder();
}

addObjectPostProcessor方法:添加用于此适配器的ObjectPostProcessor。默认实现对对象没有任何作用。

public void addObjectPostProcessor(ObjectPostProcessor<?> objectPostProcessor) {
   this.objectPostProcessor.addObjectPostProcessor(objectPostProcessor);
}

this.objectPostProcessor具体类型是一个内部类CompositeObjectPostProcessor可用于组合通过addObjectPostProcessor方法添加进来的ObjectPostProcessor对象。

private static final class CompositeObjectPostProcessor implements ObjectPostProcessor<Object> {
   private List<ObjectPostProcessor<? extends Object>> postProcessors = new ArrayList<ObjectPostProcessor<?>>();
   @Override
   public Object postProcess(Object object) {
      for(ObjectPostProcessor opp : postProcessors) {
         Class<?> oppClass = opp.getClass();
         Class<?> oppType = GenericTypeResolver.resolveTypeArgument(oppClass,ObjectPostProcessor.class);
         if(oppType == null || oppType.isAssignableFrom(object.getClass())) {
            object = opp.postProcess(object);
         }
      }
      return object;
   }
   private boolean addObjectPostProcessor(ObjectPostProcessor<? extends Object> objectPostProcessor) {
      return this.postProcessors.add(objectPostProcessor);
   }
}

2.2、AnnotationConfigurerAdapter的子类

通过1.2节的类图可知AnnotationConfigurerAdapter的子类众多,图中只是其中一小部分实现类,每种实现类配置一种AnnotationBuilder,并且还额外实现了其余的接口如DefaultStateConfigurer实现了StateConfigurer接口。

这里暂只讲解AnnotationConfigurer的子接口StateConfigurer的实现类DefaultStateConfigurer,待到后面具体用到再做具体分析,这里只需要弄清楚这些子类是如何被应用的即可。

2.2.1、DefaultStateConfigurer

这里先回顾上一篇文章《Spring Statemachine使用入门》的代码:

这里配置状态机的状态时通过调用builder.configureStates().withStates()返回的StateConfigurer对其进行配置的:

builder.configureStates()方法返回的就是StateMachineBuilder内部类Builder持有的adapter成员变量的,可以回顾一下本文开头部分和1.1.3节的内容。

public Builder() {
   adapter = new BuilderStateMachineConfigurerAdapter<S, E>();
   builder = new StateMachineConfigBuilder<S, E>();
}

public StateMachineStateConfigurer<S, E> configureStates() {
   return adapter.stateBuilder;
}

StateMachineStateBuilder实现了StateMachineStateConfigurer接口,这个接口只有一个方法:

@Override
public StateConfigurer<S, E> withStates() throws Exception {
   return apply(new DefaultStateConfigurer<S, E>());
}

当调用withStates()方法时其实就是调用了apply方法传入了一个DefaultStateConfigurer对自身做一个初始配置,并返回这个DefaultStateConfigurer对象,然后调用这个对象的配置方法.initial(States.STATE1).states(EnumSet.allOf(States.class))做一些自定义配置。

下面看一下DefaultStateConfigurer的实现:

public void configure(StateMachineStateBuilder<S, E> builder) throws Exception {
   // before passing state datas to builder, update structure
   // for missing parent, initial and end state infos.
   Collection<StateData<S, E>> stateDatas = new ArrayList<StateData<S, E>>();
   for (StateData<S, E> s : incomplete.values()) {
      s.setParent(parent);
      stateDatas.add(s);
      if (s.getState() == initialState) {
         s.setInitial(true);
         s.setInitialAction(initialAction);
      }
      if (ends.contains(s.getState())) {
         s.setEnd(true);
      }
      if (choices.contains(s.getState())) {
         s.setPseudoStateKind(PseudoStateKind.CHOICE);
      } else if (junctions.contains(s.getState())) {
         s.setPseudoStateKind(PseudoStateKind.JUNCTION);
      } else if (forks.contains(s.getState())) {
         s.setPseudoStateKind(PseudoStateKind.FORK);
      } else if (joins.contains(s.getState())) {
         s.setPseudoStateKind(PseudoStateKind.JOIN);
      } else if (entrys.contains(s.getState())) {
         s.setPseudoStateKind(PseudoStateKind.ENTRY);
      } else if (exits.contains(s.getState())) {
         s.setPseudoStateKind(PseudoStateKind.EXIT);
      }
      if (s.getState() == history) {
         if (History.SHALLOW == historyType) {
            s.setPseudoStateKind(PseudoStateKind.HISTORY_SHALLOW);
         } else if (History.DEEP == historyType) {
            s.setPseudoStateKind(PseudoStateKind.HISTORY_DEEP);
         }
      }
      s.setSubmachine(submachines.get(s.getState()));
      s.setSubmachineFactory(submachinefactories.get(s.getState()));
   }
   builder.addStateData(stateDatas);
}

上面configure方法将incomplete中保存的StateData根据不同的状态类型设置对应的pseudoStateKind属性值,然后通过builder.addStateData()方法放入到StateMachineStateBuilder的stateDatas中,然后在performBuild方法调用时会使用到这个stateDatas封装到一个StatesData对象中。

@Override
protected StatesData<S, E> performBuild() throws Exception {
   return new StatesData<S, E>(stateDatas);
}

public void addStateData(Collection<StateData<S, E>> stateDatas) {
   this.stateDatas.addAll(stateDatas);
}

incomplete是一个Map的数据结构,当调用StateConfigurer的方法时会对其进行填充,如initial方法:

@Override
public StateConfigurer<S, E> initial(S initial) {
   this.initialState = initial;
   state(initial);
   return this;
}
public StateConfigurer<S, E> state(S state, E... deferred) {
   Collection<E> d = null;
   if (deferred != null) {
      d = Arrays.asList(deferred);
   }
   addIncomplete(null, state, d, null, null, null);
   return this;
}
private void addIncomplete(Object parent, S state, Collection<E> deferred,
      Collection<? extends Action<S, E>> entryActions, Collection<? extends Action<S, E>> exitActions,
      Collection<? extends Action<S, E>> stateActions) {
   StateData<S, E> stateData = incomplete.get(state);
   if (stateData == null) {
      stateData = new StateData<S, E>(parent, region, state, deferred, entryActions, exitActions);
      incomplete.put(state, stateData);
   }
   if (stateData.getParent() == null) {
      stateData.setParent(parent);
   }
   if (stateData.getRegion() == null) {
      stateData.setRegion(region);
   }
   if (stateData.getDeferred() == null) {
      stateData.setDeferred(deferred);
   }
   if (stateData.getEntryActions() == null) {
      stateData.setEntryActions(entryActions);
   }
   if (stateData.getExitActions() == null) {
      stateData.setExitActions(exitActions);
   }
   if (stateData.getStateActions() == null) {
      stateData.setStateActions(stateActions);
   }
}

3、StateMachineFactory:创建虚拟机

状态机的创建是通过这个工厂实现的,而工厂需要的原料就是上面说的AnnotationBuilder是用来创建的对象,其中StateMachineConfig是对ConfigurationData、TransitionsData、StatesData、ModelData四种原料的组合包装。

public interface StateMachineFactory<S, E> {

   StateMachine<S, E> getStateMachine();

   StateMachine<S, E> getStateMachine(String machineId);

   StateMachine<S, E> getStateMachine(UUID uuid);
}

 StateMachineFactory定义了三个创建状态机方法,子类AbstractStateMachineFactory实现了这个三个方法。

3.1、AbstractStateMachineFactory

AbstractStateMachineFactory中实现了获取StateMachine的方法,

public StateMachine<S, E> getStateMachine(UUID uuid, String machineId) {
   ArrayList<StateMachine<S, E>> machines = new ArrayList<>();
   //通过StateMachineModelBuilder配置的StateMachineModelFactory得到一个StateMachineModel,
   StateMachineModel<S, E> stateMachineModel = resolveStateMachineModel(machineId);
   if (stateMachineModel.getConfigurationData().isVerifierEnabled()) {
      StateMachineModelVerifier<S, E> verifier = stateMachineModel.getConfigurationData().getVerifier();
      if (verifier == null) {
         verifier = new CompositeStateMachineModelVerifier<S, E>();
      }
      verifier.verify(stateMachineModel);
   }

   // shared
   DefaultExtendedState defaultExtendedState = new DefaultExtendedState();

   StateMachine<S, E> machine = null;

   // we store mappings from state id's to states which gets
   // created during the process. This is needed for transitions to
   // find a correct mappings because they use state id's, not actual
   // states.
   final Map<S, State<S, E>> stateMap = new HashMap<S, State<S, E>>();
   Stack<MachineStackItem<S, E>> regionStack = new Stack<MachineStackItem<S, E>>();
   Stack<StateData<S, E>> stateStack = new Stack<StateData<S, E>>();
   Map<Object, StateMachine<S, E>> machineMap = new HashMap<Object, StateMachine<S,E>>();
   List<HolderListItem<S, E>> holderList = new ArrayList<>();

   Iterator<Node<StateData<S, E>>> iterator = buildStateDataIterator(stateMachineModel);
   while (iterator.hasNext()) {
      Node<StateData<S, E>> node = iterator.next();
      StateData<S, E> stateData = node.getData();
      StateData<S, E> peek = stateStack.isEmpty() ? null : stateStack.peek();

      // simply push and continue
      if (stateStack.isEmpty()) {
         stateStack.push(stateData);
         continue;
      }

      boolean stackContainsSameParent = false;
      Iterator<StateData<S, E>> ii = stateStack.iterator();
      while (ii.hasNext()) {
         StateData<S, E> sd = ii.next();
         if (stateData != null && ObjectUtils.nullSafeEquals(stateData.getState(), sd.getParent())) {
            stackContainsSameParent = true;
            break;
         }
      }

      if (stateData != null && !stackContainsSameParent) {
         stateStack.push(stateData);
         continue;
      }

      Collection<StateData<S, E>> stateDatas = popSameParents(stateStack);
      int initialCount = getInitialCount(stateDatas);
      Collection<Collection<StateData<S, E>>> regionsStateDatas = splitIntoRegions(stateDatas);
      Collection<TransitionData<S, E>> transitionsData = getTransitionData(iterator.hasNext(), stateDatas, stateMachineModel);

      if (initialCount > 1) {
         for (Collection<StateData<S, E>> regionStateDatas : regionsStateDatas) {
            // try to build reqion id's
            Object rId = regionStateDatas.iterator().next().getRegion();
            String mId = machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId();
            mId = mId + "#" + (rId != null ? rId.toString() : "");

            machine = buildMachine(machineMap, stateMap, holderList, regionStateDatas, transitionsData,
                  resolveBeanFactory(stateMachineModel), contextEvents, defaultExtendedState,
                  stateMachineModel.getTransitionsData(), mId, null, stateMachineModel);
            regionStack.push(new MachineStackItem<S, E>(machine));
            machines.add(machine);
         }

         Collection<Region<S, E>> regions = new ArrayList<Region<S, E>>();
         while (!regionStack.isEmpty()) {
            MachineStackItem<S, E> pop = regionStack.pop();
            regions.add(pop.machine);
         }
         S parent = (S)peek.getParent();
         RegionState<S, E> rstate = buildRegionStateInternal(parent, regions, null,
               stateData != null ? stateData.getEntryActions() : null,
               stateData != null ? stateData.getExitActions() : null,
               new DefaultPseudoState<S, E>(PseudoStateKind.INITIAL), stateMachineModel);
         rstate.setRegionExecutionPolicy(stateMachineModel.getConfigurationData().getRegionExecutionPolicy());
         if (stateData != null) {
            stateMap.put(stateData.getState(), rstate);
         } else {
            // TODO: don't like that we create a last machine here
            Collection<State<S, E>> states = new ArrayList<State<S, E>>();
            states.add(rstate);
            Transition<S, E> initialTransition = new InitialTransition<S, E>(rstate);
            StateMachine<S, E> m = buildStateMachineInternal(states, new ArrayList<Transition<S, E>>(), rstate, initialTransition,
                  null, defaultExtendedState, null, contextEvents, resolveBeanFactory(stateMachineModel), beanName,
                  machineId != null ? machineId : stateMachineModel.getConfigurationData().getMachineId(),
                  uuid, stateMachineModel);
            machine = m;
            machines.add(m);
         }
      } else {
         machine = buildMachine(machineMap, stateMap, holderList, stateDatas, transitionsData,
               resolveBeanFactory(stateMachineModel), contextEvents, defaultExtendedState,
               stateMachineModel.getTransitionsData(), machineId, uuid, stateMachineModel);
         machines.add(machine);
         if (peek.isInitial() || (!peek.isInitial() && !machineMap.containsKey(peek.getParent()))) {
            machineMap.put(peek.getParent(), machine);
         }
      }

      stateStack.push(stateData);
   }

   // setup autostart for top-level machine
   if (machine instanceof LifecycleObjectSupport) {
      ((LifecycleObjectSupport)machine).setAutoStartup(stateMachineModel.getConfigurationData().isAutoStart());
   }

   // set top-level machine as relay
   final StateMachine<S, E> fmachine = machine;
   fmachine.getStateMachineAccessor().doWithAllRegions(function -> function.setRelay(fmachine));

   // add monitoring hooks
   final StateMachineMonitor<S, E> stateMachineMonitor = stateMachineModel.getConfigurationData().getStateMachineMonitor();
   if (stateMachineMonitor != null || defaultStateMachineMonitor != null) {
      fmachine.getStateMachineAccessor().doWithRegion(function -> {
         if (defaultStateMachineMonitor != null) {
            function.addStateMachineMonitor(defaultStateMachineMonitor);
         }
         if (stateMachineMonitor != null) {
            function.addStateMachineMonitor(stateMachineMonitor);
         }
      });
   }

   // set parent machines for each built machine
   for (Entry<Object, StateMachine<S, E>> mme : machineMap.entrySet()) {
      StateMachine<S, E> m = null;
      if (mme.getKey() != null) {
         Object sParent = null;
         for (StateData<S, E> sd : stateMachineModel.getStatesData().getStateData()) {
            if (ObjectUtils.nullSafeEquals(sd.getState(), mme.getKey())) {
               sParent = sd.getParent();
               break;
            }
         }
         m = machineMap.get(sParent);
      }
      final StateMachine<S, E> mm = m;
      mme.getValue().getStateMachineAccessor().doWithRegion(function -> function.setParentMachine(mm));
   }

   // init built machines
   for (StateMachine<S, E> m : machines) {
      ((LifecycleObjectSupport)m).afterPropertiesSet();
   }


   // TODO: should error out if sec is enabled but spring-security is not in cp
   if (stateMachineModel.getConfigurationData().isSecurityEnabled()) {
      final StateMachineSecurityInterceptor<S, E> securityInterceptor = new StateMachineSecurityInterceptor<S, E>(
            stateMachineModel.getConfigurationData().getTransitionSecurityAccessDecisionManager(),
            stateMachineModel.getConfigurationData().getEventSecurityAccessDecisionManager(),
            stateMachineModel.getConfigurationData().getEventSecurityRule());
      log.info("Adding security interceptor " + securityInterceptor);
      fmachine.getStateMachineAccessor()
            .doWithAllRegions(function -> function.addStateMachineInterceptor(securityInterceptor));
   }

   // setup distributed state machine if needed.
   // we wrap previously build machine with a distributed
   // state machine and set it to use given ensemble.
   if (stateMachineModel.getConfigurationData().getStateMachineEnsemble() != null) {
      DistributedStateMachine<S, E> distributedStateMachine = new DistributedStateMachine<S, E>(
            stateMachineModel.getConfigurationData().getStateMachineEnsemble(), machine);
      distributedStateMachine.setAutoStartup(stateMachineModel.getConfigurationData().isAutoStart());
      distributedStateMachine.afterPropertiesSet();
      machine = distributedStateMachine;
   }

   for (StateMachineListener<S, E> listener : stateMachineModel.getConfigurationData().getStateMachineListeners()) {
      machine.addStateListener(listener);
   }

   List<StateMachineInterceptor<S,E>> interceptors = stateMachineModel.getConfigurationData().getStateMachineInterceptors();
   if (interceptors != null) {

      for (final StateMachineInterceptor<S, E> interceptor : interceptors) {
         // add persisting interceptor hooks to all regions
         RegionPersistingInterceptorAdapter<S, E> adapter = new RegionPersistingInterceptorAdapter<>(interceptor, machine);
         machine.getStateMachineAccessor().doWithAllRegions(function -> function.addStateMachineInterceptor(adapter));
      }
   }

   // go through holders and fix state references which
   // were not known at a time holder was created
   for (HolderListItem<S, E> holderItem : holderList) {
      holderItem.value.setState(stateMap.get(holderItem.key));
   }

   return delegateAutoStartup(machine);
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值