ワークフローフレームワークActivityソース学習(一)

64292 ワード

仕事の都合でワークフローフレームワークactiviti 5を使う必要があるので、少し時間をかけて検討しましたが、今日は少し時間をかけて整理して、初めて書くのがよくありませんので、ご了承ください.まず、私はテストdemoを書きました.以下のようにします.
static ProcessEngine processEngine = null;

    static {
        processEngine = ProcessEngines.getDefaultProcessEngine();
    }

    @Test
    public void test1() {
        RepositoryService repositoryService = processEngine.getRepositoryService();
        repositoryService.createDeployment()
                .name(" ")
                .addClasspathResource("processes/serviceTaskDemo.bpmn")
                .deploy();

        RuntimeService runtimeService = processEngine.getRuntimeService();

        String businessKey = UUIDUtils.generateShortUuid();
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess_7", businessKey, null);

        System.out.println();
    }1

最初のステップはプロセスエンジンの取得です
processEngine = ProcessEngines.getDefaultProcessEngine();

debugが中に入るとデフォルトのプロセスエンジンが得られます
 public static ProcessEngine getDefaultProcessEngine() {
    return getProcessEngine(NAME_DEFAULT);
  }

次に、プロセスエンジンが初期化されたかどうかを判断します.
 public static ProcessEngine getProcessEngine(String processEngineName) {
    if (!isInitialized()) {
      init();
    }
    return processEngines.get(processEngineName);
  }

初期化がプロセスエンジン名で直接取得される場合、processEnginesはmapマッピングであり、そうでなければ初期化が開始されます.
初期化メソッドに進む
public synchronized static void init() {
    if (!isInitialized()) {
      if(processEngines == null) {
        // Create new map to store process-engines if current map is null
        processEngines = new HashMap<String, ProcessEngine>();        
      }
      ClassLoader classLoader = ReflectUtil.getClassLoader();
      Enumeration<URL> resources = null;
      try {
        resources = classLoader.getResources("activiti.cfg.xml");
      } catch (IOException e) {
        throw new ActivitiIllegalArgumentException("problem retrieving activiti.cfg.xml resources on the classpath: "+System.getProperty("java.class.path"), e);
      }
      
      // Remove duplicated configuration URL's using set. Some classloaders may return identical URL's twice, causing duplicate startups
      Set<URL> configUrls = new HashSet<URL>();
      while (resources.hasMoreElements()) {
        configUrls.add( resources.nextElement() );
      }
      for (Iterator<URL> iterator = configUrls.iterator(); iterator.hasNext();) {
        URL resource = iterator.next();
        log.info("Initializing process engine using configuration '{}'",  resource.toString());
        initProcessEnginFromResource(resource);
      }
      
      try {
        resources = classLoader.getResources("activiti-context.xml");
      } catch (IOException e) {
        throw new ActivitiIllegalArgumentException("problem retrieving activiti-context.xml resources on the classpath: "+System.getProperty("java.class.path"), e);
      }
      while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        log.info("Initializing process engine using Spring configuration '{}'",  resource.toString());
        initProcessEngineFromSpringResource(resource);
      }

      setInitialized(true);
    } else {
      log.info("Process engines already initialized");
    }
  }


まず、プロセスエンジンの具体的な実装クラスのクラスローダを使用してプロファイルactivitiをロードする.cfg.xml setコレクションを使用してファイルパスを再構成
 Set<URL> configUrls = new HashSet<URL>();
      while (resources.hasMoreElements()) {
        configUrls.add( resources.nextElement() );
      }

プロファイルパスを使用してプロセス情報を初期化
private static ProcessEngineInfo initProcessEnginFromResource(URL resourceUrl) {
    ProcessEngineInfo processEngineInfo = processEngineInfosByResourceUrl.get(resourceUrl.toString());
    // if there is an existing process engine info
    if (processEngineInfo!=null) {
      // remove that process engine from the member fields
      processEngineInfos.remove(processEngineInfo);
      if (processEngineInfo.getException()==null) {
        String processEngineName = processEngineInfo.getName();
        processEngines.remove(processEngineName);
        processEngineInfosByName.remove(processEngineName);
      }
      processEngineInfosByResourceUrl.remove(processEngineInfo.getResourceUrl());
    }

    String resourceUrlString = resourceUrl.toString();
    try {
      log.info("initializing process engine for resource {}", resourceUrl);
      ProcessEngine processEngine = buildProcessEngine(resourceUrl);
      String processEngineName = processEngine.getName();
      log.info("initialised process engine {}", processEngineName);
      processEngineInfo = new ProcessEngineInfoImpl(processEngineName, resourceUrlString, null);
      processEngines.put(processEngineName, processEngine);
      processEngineInfosByName.put(processEngineName, processEngineInfo);
    } catch (Throwable e) {
      log.error("Exception while initializing process engine: {}", e.getMessage(), e);
      processEngineInfo = new ProcessEngineInfoImpl(null, resourceUrlString, getExceptionString(e));
    }
    processEngineInfosByResourceUrl.put(resourceUrlString, processEngineInfo);
    processEngineInfos.add(processEngineInfo);
    return processEngineInfo;
  }

まず、プロファイルパスからプロセス情報を取得し、取得しない場合はプロファイルパスからプロセス情報を作成します.
ProcessEngine processEngine = buildProcessEngine(resourceUrl);

プロファイル情報の場所を取得してファイル情報を読み込むには、主にストリーム操作を使用します.
private static  ProcessEngine buildProcessEngine(URL resource) {
    InputStream inputStream = null;
    try {
      inputStream = resource.openStream();
      ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration.createProcessEngineConfigurationFromInputStream(inputStream);
      return processEngineConfiguration.buildProcessEngine();
      
    } catch (IOException e) {
      throw new ActivitiIllegalArgumentException("couldn't open resource stream: "+e.getMessage(), e);
    } finally {
      IoUtil.closeSilently(inputStream);
    }
  }

取得したプロセスプロファイルからプロセスエンジンを構築
processEngineConfiguration.buildProcessEngine();

中に入ると、debugデバッグを使用して発見されたのは***P r o cessEngineConfigurationImpl***であり、このクラスはワークフロー初期化の核心である抽象的な方法であることがわかります.
すべてのワークフローサービスが含まれています
protected RepositoryService repositoryService = new RepositoryServiceImpl();
  protected RuntimeService runtimeService = new RuntimeServiceImpl();
  protected HistoryService historyService = new HistoryServiceImpl(this);
  protected IdentityService identityService = new IdentityServiceImpl();
  protected TaskService taskService = new TaskServiceImpl(this);
  protected FormService formService = new FormServiceImpl();
  protected ManagementService managementService = new ManagementServiceImpl();
  protected DynamicBpmnService dynamicBpmnService = new DynamicBpmnServiceImpl(this);
  

コマンド設定
 protected CommandConfig defaultCommandConfig;
  protected CommandConfig schemaCommandConfig;

ブロッキング
 /** the configurable list which will be {@link #initInterceptorChain(java.util.List) processed} to build the {@link #commandExecutor} */
  protected List<CommandInterceptor> customPreCommandInterceptors;
  protected List<CommandInterceptor> customPostCommandInterceptors;
  
  protected List<CommandInterceptor> commandInterceptors;

  /** this will be initialized during the configurationComplete() */
  protected CommandExecutor commandExecutor;

ibatisなどのデータベース関連操作
 protected List<SessionFactory> customSessionFactories;
  protected DbSqlSessionFactory dbSqlSessionFactory;
  protected Map<Class<?>, SessionFactory> sessionFactories;

ぶんせきき
protected BpmnDeployer bpmnDeployer;
  protected BpmnParser bpmnParser;
  protected List<Deployer> customPreDeployers;
  protected List<Deployer> customPostDeployers;
  protected List<Deployer> deployers;
  protected DeploymentManager deploymentManager;

では、サービスTaskServiceを例に、complete()機能の具体的な実装クラスに入ると、次のような操作が発見されます.
 public void complete(String taskId) {
    commandExecutor.execute(new CompleteTaskCmd(taskId, null));
  }

このような実現方式を見ると、activitiフレームワーク設計に使用されるコマンドモードと責任チェーンモードactivitiのすべての操作はこのモードであり、動作を1つのコマンドにパッケージし、動作と動作を実行する行為を十分にデカップリングし、動作周辺に関連するいくつかの操作をブロックチェーンに配置し、階層をより明確にしなければならない.
例えば、このcommandExecutorというアクチュエータは、実際にはP o n s e n g i n e ConfigurationImplで初期化され、デフォルトのブロッキングを追加して見つかりました.
protected void init() {
  	initConfigurators();
  	configuratorsBeforeInit();
    initProcessDiagramGenerator();
    initHistoryLevel();
    initExpressionManager();
    initDataSource();
    initVariableTypes();
    initBeans();
    initFormEngines();
    initFormTypes();
    initScriptingEngines();
    initClock();
    initBusinessCalendarManager();
    initCommandContextFactory();
    initTransactionContextFactory();
    initCommandExecutors();
    initServices();
    initIdGenerator();
    initDeployers();
    initJobHandlers();
    initJobExecutor();
    initAsyncExecutor();
    initTransactionFactory();
    initSqlSessionFactory();
    initSessionFactories();
    initJpa();
    initDelegateInterceptor();
    initEventHandlers();
    initFailedJobCommandFactory();
    initEventDispatcher();
    initProcessValidator();
    initDatabaseEventLogging();
    configuratorsAfterInit();
  }


見つける
protected void initServices() {
    initService(repositoryService);
    initService(runtimeService);
    initService(historyService);
    initService(identityService);
    initService(taskService);
    initService(formService);
    initService(managementService);
    initService(dynamicBpmnService);
  }


見つける
protected void initService(Object service) {
    if (service instanceof ServiceImpl) {
      ((ServiceImpl)service).setCommandExecutor(commandExecutor);
    }
  }

インターセプタがServiceImplに設定されているのがわかりますが、問題が発生しました.ServiceImplは何ですか.これはちょっと待ってください.
まず、このブロッキングがどのように初期化されて前のレイヤに戻るかを見てみましょう.
 protected void init() {
  	initConfigurators();
  	configuratorsBeforeInit();
    initProcessDiagramGenerator();
    initHistoryLevel();
    initExpressionManager();
    initDataSource();
    initVariableTypes();
    initBeans();
    initFormEngines();
    initFormTypes();
    initScriptingEngines();
    initClock();
    initBusinessCalendarManager();
    initCommandContextFactory();
    initTransactionContextFactory();
    *initCommandExecutors();*
    *initServices();*
    initIdGenerator();
    initDeployers();
    initJobHandlers();
    initJobExecutor();
    initAsyncExecutor();
    initTransactionFactory();
    initSqlSessionFactory();
    initSessionFactories();
    initJpa();
    initDelegateInterceptor();
    initEventHandlers();
    initFailedJobCommandFactory();
    initEventDispatcher();
    initProcessValidator();
    initDatabaseEventLogging();
    configuratorsAfterInit();
  }

ブロッキングがサービスの前で初期化されているのがわかります
に入る
 protected void initCommandExecutors() {
    initDefaultCommandConfig();
    initSchemaCommandConfig();
    initCommandInvoker();
    initCommandInterceptors();
    initCommandExecutor();
  }

InitCommandInterceptors()初期化ブロッキングエントリが見つかりました
protected void initCommandInterceptors() {
    if (commandInterceptors==null) {
      commandInterceptors = new ArrayList<CommandInterceptor>();
      if (customPreCommandInterceptors!=null) {
        commandInterceptors.addAll(customPreCommandInterceptors);
      }
      commandInterceptors.addAll(getDefaultCommandInterceptors());
      if (customPostCommandInterceptors!=null) {
        commandInterceptors.addAll(customPostCommandInterceptors);
      }
      commandInterceptors.add(commandInvoker);
    }
  }

3つのブロッキングがロードされます.customPreCommandInterceptors(コマンド実行前)、getDefaultCommandInterceptors(デフォルトのブロッキング)、customPostCommandInterceptors(コマンド実行後)
デフォルトのブロッキングに入ります
protected Collection< ? extends CommandInterceptor> getDefaultCommandInterceptors() {
    List<CommandInterceptor> interceptors = new ArrayList<CommandInterceptor>();
    interceptors.add(new LogInterceptor());
    
    CommandInterceptor transactionInterceptor = createTransactionInterceptor();
    if (transactionInterceptor != null) {
      interceptors.add(transactionInterceptor);
    }
    
    interceptors.add(new CommandContextInterceptor(commandContextFactory, this));
    return interceptors;
  }

ログ・ブロッカーとトランザクション・ブロッカーがデフォルトでロードされていることがわかります.
public class LogInterceptor extends AbstractCommandInterceptor {
  
  private static Logger log = LoggerFactory.getLogger(LogInterceptor.class);

  public <T> T execute(CommandConfig config, Command<T> command) {
    if (!log.isDebugEnabled()) {
      // do nothing here if we cannot log
      return next.execute(config, command);
    }
    log.debug("
"
); log.debug("--- starting {} --------------------------------------------------------", command.getClass().getSimpleName()); try { return next.execute(config, command); } finally { log.debug("--- {} finished --------------------------------------------------------", command.getClass().getSimpleName()); log.debug("
"
); } } }

トランザクション・ブロッカーはspringを使用してトランザクションを含む伝播レベルと独立性レベルを統合します.
次に、上記の問題を解析します.ServiceImplは何ですか.TaskServiceを含むすべてのサービスがServiceImplを継承すると、すべてのサービスにこのデフォルトの初期化ブロッカーがあります.