【CSII-PE】关于Template和Transaction中配置的Action执行顺序

关于TemplateTransaction中配置的Action执行顺序

在系统的template.xml中可以看到相关template的定义:


而且在Transaction的定义中不但指定了template,还给自己指定action:


    
        QueryPSecretnoticeAction
    
    
        
    
    
        
            stream,
        
    

这两个地方都指定了action,那么执行的时候到底是按什么规则执行了。这里可以看到模版中定义了一个名为action的Action,交易中也定义了一个名为action的Action。那么这两个action在程序执行的时候到底执行谁呢?还有一点,template中名为action的Action对应的是Placeholder,那么看名字就知道是占位符作用,这里为什么要用一个占位符呢?为什么不直接省略掉?

这些疑问都在相关Template的实现中可以找到答案,不同的template对这些Action的处理方式和顺序都不相同。

先看publicQueryTemplate它的实现类ExecutableSequenceTemplate的代码:

public class ExecutableSequenceTemplateextends AbstractSequenceTemplate{
  public ExecutableSequenceTemplate() {}
  
  protected void doInternal(Context context, Action action) throws PeException{
    if ((action instanceof Executable)) {
        ((Executable)action).execute(context);
    } else {
        throw new PeException("system.executable_mismatch", 
        new Object[] { action.getClass().getName(), context.getTransactionId() });
    }
  }
}

就一个doInternal方法,对传入进来的Action进行了类型判断,并且进行了调用。看template的入口execute方法(这里在父类中):

public void execute(final Context context)throws PeException{
    final Map actions;

    if (getActions() == null){
      Map actions = context.getTransactionConfig().getActions();
      if (actions != null) {}
    }else{
      actions = getActions();
    }
    
    if (transactionEnabled){

      getTransactionTemplate().execute(new TransactionCallback(){
            public Object doInTransaction(TransactionStatus arg0)
            {
              try
              {
                for (Iterator it = actions.keySet().iterator(); it.hasNext();)
                {

                  Action action = getAction((String)it.next(), context);
                  

                  if ((action instanceof PlaceholderAction)) {
                    throw new PeException("system.placeholders_error", 
                      new Object[] { getClass().getName(), context.getTransactionId() });
                  }
                  doInternal(context, action);
                }
               
              }
              catch (PeException e)
              {
                throw new PeRuntimeException(e.getMessageKey(), e.getCause(), e.getArgs());
              }
              return null;

            }
        
      });
      
    }else{
   
      for (Iterator it = actions.keySet().iterator(); it.hasNext();){

        Action action = getAction((String)it.next(), context);
        
        if ((action instanceof PlaceholderAction)) {
          throw new PeException("system.placeholders_error", 
            new Object[] { getClass().getName(), context.getTransactionId() });
        }
        doInternal(context, action);
      }
    }
}

上面的代码主要过程就是先判断template自己有没有配置Action,如果没有配置那么就直接获取Transaction中配置的Action。然后遍历Action的名字,将配置的action的名字传递到getAction方法中来获取对应的Action,最后将获取到的Action交给doInternal方法来执行。这里可以看到ExecutableSequenceTemplate对Action的处理方式就是直接遍历执行。

接下来看getAction方法(在父类AbstractTemplate中):

protected Action getAction(String paramString, Context paramContext) {

    //优先从Transaction配置中获取对应的Action
    Map localMap = paramContext.getTransactionConfig().getActions();
    if (localMap == null) {
      localObject = getActions().get(paramString);
      return (Action)localObject;
    }
    Object localObject = localMap.get(paramString);
    if (localObject == null) {
      localObject = getActions().get(paramString);
    }
    return (Action)localObject;
}

这里可以看到,getAction方法会优先获取Transaction中配置的同名Action,也就是说名字相同的Action,Transaction的配置可以覆盖Template的配置(所有通过AbstractTemplate.getAction(name,context)的方式均适用)。

接着看publicTwoPhaseTrsTemplate对应的实现类TwoPhaseTrsTemplate:

public void execute(final Context context) throws PeException {

    Action preAction = getAction("preAction", context);
    Action aftAction = getAction("aftAction", context);
    final Action action = getAction("action", context);
    
    if ((action instanceof PlaceholderAction)) {
      throw new PeException("system.placeholders_error", 
        new Object[] { getClass().getName(), context.getTransactionId() });
    }
    
    if (!(action instanceof Submitable)) {
      throw new PeException("system.placeholders_error", 
        new Object[] { getClass().getName(), context.getTransactionId(), action.getClass().getName() });
    }
    if ((action instanceof Preparable)) {
      ((Preparable)action).prepare(context);
    }
    
    if (preAction != null) {
      ((Executable)preAction).execute(context);
    }
    try {
      if (transactionEnabled) {

        getTransactionTemplate().execute(new TransactionCallback() {
          public Object doInTransaction(TransactionStatus arg0) {
            try {
              ((Submitable)action).submit(context);
            }
            catch (PeException e) {
                //异常处理代码
            }
            return null;
          }
          

        });
      } else {
        ((Submitable)action).submit(context);
      }
      context.setData("_JnlStatus", "0");
    }
    catch (Exception e) {
      //异常处理代码
    } finally {
      if (aftAction != null) {
        ((Executable)aftAction).execute(context);
      }
    }
}

通过代码可以看到,对于TwoPhaseTrsTemplate来说,它只会调用三个Action,而不想前面的ExecutableSequenceTemplate会遍历调用所有配置的Action,当然它同样可以在Transaction中配置Action来覆盖Template中配置的Action(因为它也是使用AbstractTemplate.getAction方法来获取Action)

by CSII@王大仙

你可能感兴趣的:(PE)