activiti 监听引擎启动和初始化



1.1.1. 前言

用户故事:现在有这样一个需求,第一个需求:公司的开发环境,测试环境以及线上环境,我们使用的数据库是不一样的,我们必须能够任意的切换数据库进行测试和发布,对数据库连接字符串我们需要加密,保证我们的数据库连接不能被发现。必须确保我们的数据库不能暴露出去,第二个需求,我们需要监控activiti 工作流引擎,在流程启动的之前,我们要保证我们的所有属性都注入进去,如果有些属性没有注入进去,我们是不能让流程启动起来的。也就是进行必要饿属性检测,如果没有期望的属性,直接报错,在流程实例化之后,输出log日志,确保我们的属性都是正确的。并且监控引擎中所有的值

第一个需求如何解决呢?

我们来看一下常规的数据库配置,程序的配置如下:

 <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

      <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti"/>

        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>

        <property name="jdbcUsername" value="root"/>

  <property name="jdbcPassword" value="123"/>

 </bean>

看到上面的配置,是不是似曾相识的感觉,没错就是这么简单,但是如何确保能任意的切换呢,仔细想想还是很简单的,那里变化隔离那里嘛,这个时候我们可以把这些这些变化的东西隔离出去,放到jdbc.properties中,新建jdbc.properties把变化的内容设置进去到jdbc.propertiesjdbc.properties内容如下:

jdbcUrl=jdbc:mysql://localhost:3306/activiti

jdbcDriver=com.mysql.jdbc.Driver

jdbcUsername=root

jdbcPassword=123

上面把变化的东西隔离出来,那程序怎么能够使用jdbc.properties中的配置信息呢?这是一个很关键的问题,我们之前用的activiti版本是5.12,所以当时的设计就是修改源码,主要修改org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl类,在init()方法中我们设计一个钩子函数,然后子类负责实现上面的这些功能,主要就修改的类是org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl,修改ProcessEngineConfigurationImpl类中的数据库连接的信息,由于目前最新的版本activiti 5.19版本,这个版本已经支持了这种实现,具体的实现都差不多,只是我们不用修改源码,直接扩展了,这不就是软件设计中的开闭原则。对新增开放对修改关闭。

下面看下activiti 5.19是如何可以实现这种功能需求的。

1.1.2. activiti 源码

首先看一下org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl类中的init()方法哪个可以实现这种需求,了解底层内核实现才能很方便的扩展嘛。

ProcessEngineConfigurationImpl中的init()部分方法如下:

//初始化configurators集合

initConfigurators();

//调用configurator.beforeInit方法

configuratorsBeforeInit();

...

//调用configurator.configure()方法

configuratorsAfterInit();

上面的三个核心方法实现如下所示:

内部ServiceLoader可以参考java.util.ServiceLoader使用http://blog.csdn.net/qq_30739519/article/details/51164954这篇文章

  1. protected List<ProcessEngineConfigurator> configurators;  
  2. protected List<ProcessEngineConfigurator> allConfigurators;  
  3.  protected boolean enableConfiguratorServiceLoader = true// Enabled by default. In certain environments this should be set to false (eg osgi)  
  4.   protected void initConfigurators() {  
  5.   //初始化数组集合  
  6.   allConfigurators = new ArrayList<ProcessEngineConfigurator>();  
  7.     
  8.   // Configurators that are explicitely added to the config  
  9. //如果集合存在值就循环添加进去  
  10.     if (configurators != null) {  
  11.       for (ProcessEngineConfigurator configurator : configurators) {  
  12.         allConfigurators.add(configurator);  
  13.       }  
  14.     }  
  15.       
  16.     // Auto discovery through ServiceLoader 默认是true  
  17.     if (enableConfiguratorServiceLoader) {  
  18.     ClassLoader classLoader = getClassLoader();  
  19.     if (classLoader == null) {  
  20.     classLoader = ReflectUtil.getClassLoader();  
  21.     }  
  22.     //循环添加进去  
  23.     ServiceLoader<ProcessEngineConfigurator> configuratorServiceLoader  
  24.     = ServiceLoader.load(ProcessEngineConfigurator.class, classLoader);  
  25.     int nrOfServiceLoadedConfigurators = 0;  
  26.     for (ProcessEngineConfigurator configurator : configuratorServiceLoader) {  
  27.     allConfigurators.add(configurator);  
  28.     nrOfServiceLoadedConfigurators++;  
  29.     }  
  30.       
  31.     if (nrOfServiceLoadedConfigurators > 0) {  
  32.     log.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators++, nrOfServiceLoadedConfigurators > 1 ? "s" : "");  
  33.     }  
  34.     //如果集合不为空 存在多个值的话就按照升序排列 根据什么作为排序规则呢,很显然根据getPriority中的值进行排序 比如a类getPriority 10 b类getPriority 100 那么排序后就是 a,b现执行a类对的再执行b类的。  
  35.     if (!allConfigurators.isEmpty()) {  
  36.       
  37.     // Order them according to the priorities (usefule for dependent configurator)  
  38.     Collections.sort(allConfigurators, new Comparator<ProcessEngineConfigurator>() {  
  39.     @Override  
  40.     public int compare(ProcessEngineConfigurator configurator1, ProcessEngineConfigurator configurator2) {  
  41.     int priority1 = configurator1.getPriority();  
  42.     int priority2 = configurator2.getPriority();  
  43.       
  44.     if (priority1 < priority2) {  
  45.     return -1;  
  46.     } else if (priority1 > priority2) {  
  47.     return 1;  
  48.     }   
  49.     return 0;  
  50.     }  
  51. });  
  52.       
  53.     // Execute the configurators  
  54.     log.info("Found {} Process Engine Configurators in total:", allConfigurators.size());  
  55.     for (ProcessEngineConfigurator configurator : allConfigurators) {  
  56.     log.info("{} (priority:{})", configurator.getClass(), configurator.getPriority());  
  57.     }  
  58.       
  59.     }  
  60.       
  61.     }  
  62.   }  
  63.   //循环所有allConfigurators 执行beforeInit方法  
  64.   protected void configuratorsBeforeInit() {  
  65.   for (ProcessEngineConfigurator configurator : allConfigurators) {  
  66.   log.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority());  
  67.   configurator.beforeInit(this);  
  68.   }  
  69.   }  
  70.   //循环所有allConfigurators 执行configuratorsAfterInit方法  
  71.   protected void configuratorsAfterInit() {  
  72.   for (ProcessEngineConfigurator configurator : allConfigurators) {  
  73.   log.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority());  
  74.   configurator.configure(this);  
  75.   }  
  76.   }  
protected List<ProcessEngineConfigurator> configurators;
protected List<ProcessEngineConfigurator> allConfigurators;
 protected boolean enableConfiguratorServiceLoader = true; // Enabled by default. In certain environments this should be set to false (eg osgi)
  protected void initConfigurators() {
  //初始化数组集合
  allConfigurators = new ArrayList<ProcessEngineConfigurator>();
  
  // Configurators that are explicitely added to the config
//如果集合存在值就循环添加进去
    if (configurators != null) {
      for (ProcessEngineConfigurator configurator : configurators) {
        allConfigurators.add(configurator);
      }
    }
    
    // Auto discovery through ServiceLoader 默认是true
    if (enableConfiguratorServiceLoader) {
    ClassLoader classLoader = getClassLoader();
    if (classLoader == null) {
    classLoader = ReflectUtil.getClassLoader();
    }
    //循环添加进去
    ServiceLoader<ProcessEngineConfigurator> configuratorServiceLoader
    = ServiceLoader.load(ProcessEngineConfigurator.class, classLoader);
    int nrOfServiceLoadedConfigurators = 0;
    for (ProcessEngineConfigurator configurator : configuratorServiceLoader) {
    allConfigurators.add(configurator);
    nrOfServiceLoadedConfigurators++;
    }
    
    if (nrOfServiceLoadedConfigurators > 0) {
    log.info("Found {} auto-discoverable Process Engine Configurator{}", nrOfServiceLoadedConfigurators++, nrOfServiceLoadedConfigurators > 1 ? "s" : "");
    }
    //如果集合不为空 存在多个值的话就按照升序排列 根据什么作为排序规则呢,很显然根据getPriority中的值进行排序 比如a类getPriority 10 b类getPriority 100 那么排序后就是 a,b现执行a类对的再执行b类的。
    if (!allConfigurators.isEmpty()) {
    
    // Order them according to the priorities (usefule for dependent configurator)
    Collections.sort(allConfigurators, new Comparator<ProcessEngineConfigurator>() {
    @Override
    public int compare(ProcessEngineConfigurator configurator1, ProcessEngineConfigurator configurator2) {
    int priority1 = configurator1.getPriority();
    int priority2 = configurator2.getPriority();
    
    if (priority1 < priority2) {
    return -1;
    } else if (priority1 > priority2) {
    return 1;
    } 
    return 0;
    }
});
    
    // Execute the configurators
    log.info("Found {} Process Engine Configurators in total:", allConfigurators.size());
    for (ProcessEngineConfigurator configurator : allConfigurators) {
    log.info("{} (priority:{})", configurator.getClass(), configurator.getPriority());
    }
    
    }
    
    }
  }
  //循环所有allConfigurators 执行beforeInit方法
  protected void configuratorsBeforeInit() {
  for (ProcessEngineConfigurator configurator : allConfigurators) {
  log.info("Executing beforeInit() of {} (priority:{})", configurator.getClass(), configurator.getPriority());
  configurator.beforeInit(this);
  }
  }
  //循环所有allConfigurators 执行configuratorsAfterInit方法
  protected void configuratorsAfterInit() {
  for (ProcessEngineConfigurator configurator : allConfigurators) {
  log.info("Executing configure() of {} (priority:{})", configurator.getClass(), configurator.getPriority());
  configurator.configure(this);
  }
  }


1.1.3. activiti 动态配置实战

好了上面说了源码的实现,下面来点干货吧,看看如何使用自定义的类实现修改配置文件。

我们使用两个类看他们的执行过程是否跟上面源码解析的一直:

定义com.daling.ch1.init.MyProcessEngineConfigurator1如下所示:

  1. @Service  
  2. public class MyProcessEngineConfigurator1 extends  AbstractProcessEngineConfigurator{  
  3. public static int DEFAULT_CONFIGURATOR_PRIORITY = 100;  
  4. public void beforeInit(  
  5. ProcessEngineConfigurationImpl processEngineConfiguration) {  
  6. System.out.println("1111111111111");  
  7. }  
  8.    
  9. public void configure(  
  10. ProcessEngineConfigurationImpl processEngineConfiguration) {  
  11. }  
  12. @Override  
  13. public int getPriority() {  
  14. return DEFAULT_CONFIGURATOR_PRIORITY;  
  15. }  
  16.    
  17. }  
  18. 定义com.daling.ch1.init.MyProcessEngineConfigurator2如下所示:  
  19.    
  20. @Service  
  21. public class MyProcessEngineConfigurator2 extends  AbstractProcessEngineConfigurator{  
  22. public static int DEFAULT_CONFIGURATOR_PRIORITY = 200;  
  23. public void beforeInit(  
  24. ProcessEngineConfigurationImpl processEngineConfiguration) {  
  25. System.out.println("2222222222222222");  
  26. }  
  27.    
  28. public void configure(  
  29. ProcessEngineConfigurationImpl processEngineConfiguration) {  
  30. }  
  31. @Override  
  32. public int getPriority() {  
  33. return DEFAULT_CONFIGURATOR_PRIORITY;  
  34. }  
  35.    
  36. }  
@Service
public class MyProcessEngineConfigurator1 extends  AbstractProcessEngineConfigurator{
public static int DEFAULT_CONFIGURATOR_PRIORITY = 100;
public void beforeInit(
ProcessEngineConfigurationImpl processEngineConfiguration) {
System.out.println("1111111111111");
}
 
public void configure(
ProcessEngineConfigurationImpl processEngineConfiguration) {
}
@Override
public int getPriority() {
return DEFAULT_CONFIGURATOR_PRIORITY;
}
 
}
定义com.daling.ch1.init.MyProcessEngineConfigurator2如下所示:
 
@Service
public class MyProcessEngineConfigurator2 extends  AbstractProcessEngineConfigurator{
public static int DEFAULT_CONFIGURATOR_PRIORITY = 200;
public void beforeInit(
ProcessEngineConfigurationImpl processEngineConfiguration) {
System.out.println("2222222222222222");
}
 
public void configure(
ProcessEngineConfigurationImpl processEngineConfiguration) {
}
@Override
public int getPriority() {
return DEFAULT_CONFIGURATOR_PRIORITY;
}
 
}


在spring中开启 包的扫描代码: <context:component-scan base-package="com"/> 

activiti 引擎配置如下所示:

 <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">

        <property name="jdbcUrl" value="jdbc:mysql://localhost3306/activiti"></property>

        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>

        <property name="jdbcUsername" value="root"/>

        <property name="jdbcPassword" value="a"/>

    

    <property name="configurators">

    <list>

   <bean class="com.daling.ch1.init.MyProcessEngineConfigurator2"></bean>

     <bean class="com.daling.ch1.init.MyProcessEngineConfigurator1"></bean>

    </list>

    </property>

<property name="activityFontName" value="宋体"></property>

   </bean>

测试代码如下:

ProcessEnginesDemodemo =new ProcessEnginesDemo();

RepositoryServicerepositoryService2 =demo.getRepositoryService();

先来运行一下程序看输出是否正确,部分输出如下所示:

1111111111111

20:20:18.245 [main] INFO  o.a.e.i.c.ProcessEngineConfigurationImpl - Executing beforeInit() of class com.daling.ch1.init.MyProcessEngineConfigurator2 (priority:200)

2222222222222222

确实说明了程序的执行顺序就是按照getPriority()方法值升序执行的。

ProcessEngineConfigurator类的定义如下:

  1. public interface ProcessEngineConfigurator {  
  2. /** 
  3.  * Called <b>before</b> any initialisation has been done. 
  4.  * This can for example be useful to change configuration settings 
  5.  * before anything that uses those properties is created. 
  6.  * 
  7.  * Allows to tweak the process engine by passing the {@link ProcessEngineConfigurationImpl} 
  8.    * which allows tweaking it programmatically. 
  9.  * 
  10.  * An example is the jdbc url. When a {@link ProcessEngineConfigurator} instance 
  11.  * wants to change it, it needs to do it in this method, or otherwise 
  12.  * the datasource would already have been created with the 'old' value 
  13.  * for the jdbc url. 
  14.  */  
  15. void beforeInit(ProcessEngineConfigurationImpl processEngineConfiguration);  
  16.     
  17.   /** 
  18.    * Called when the engine boots up, before it is usable, but after 
  19.    * the initialisation of internal objects is done. 
  20.    *   
  21.    * Allows to tweak the process engine by passing the {@link ProcessEngineConfigurationImpl} 
  22.    * which allows tweaking it programmatically. 
  23.    * 
  24.    * An example is the ldap user/group manager, which is an addition to the engine. 
  25.    * No default properties need to be overridden for this (otherwise the {@link #beforeInit(ProcessEngineConfigurationImpl)}  
  26.    * method should be used) so the logic contained in this method is executed 
  27.    * after initialisation of the default objects. 
  28.    * 
  29.    * Probably a better name would be 'afterInit' (cfr {@link #beforeInit(ProcessEngineConfigurationImpl)}), 
  30.    * but not possible due to backwards compatibility. 
  31.    */  
  32.   void configure(ProcessEngineConfigurationImpl processEngineConfiguration);  
  33.     
  34.   /** 
  35.    * When the {@link ProcessEngineConfigurator} instances are used, they are first 
  36.    * ordered by this priority number (lowest to highest). 
  37.    * If you have dependencies between {@link ProcessEngineConfigurator} 
  38.    * instances, use the priorities accordingly to order them as needed. 
  39.    */  
  40.   int getPriority();  
  41.    
  42. }  
public interface ProcessEngineConfigurator {
/**
 * Called <b>before</b> any initialisation has been done.
 * This can for example be useful to change configuration settings
 * before anything that uses those properties is created.
 *
 * Allows to tweak the process engine by passing the {@link ProcessEngineConfigurationImpl}
   * which allows tweaking it programmatically.
 *
 * An example is the jdbc url. When a {@link ProcessEngineConfigurator} instance
 * wants to change it, it needs to do it in this method, or otherwise
 * the datasource would already have been created with the 'old' value
 * for the jdbc url.
 */
void beforeInit(ProcessEngineConfigurationImpl processEngineConfiguration);
  
  /**
   * Called when the engine boots up, before it is usable, but after
   * the initialisation of internal objects is done.
   *  
   * Allows to tweak the process engine by passing the {@link ProcessEngineConfigurationImpl}
   * which allows tweaking it programmatically.
   *
   * An example is the ldap user/group manager, which is an addition to the engine.
   * No default properties need to be overridden for this (otherwise the {@link #beforeInit(ProcessEngineConfigurationImpl)} 
   * method should be used) so the logic contained in this method is executed
   * after initialisation of the default objects.
   *
   * Probably a better name would be 'afterInit' (cfr {@link #beforeInit(ProcessEngineConfigurationImpl)}),
   * but not possible due to backwards compatibility.
   */
  void configure(ProcessEngineConfigurationImpl processEngineConfiguration);
  
  /**
   * When the {@link ProcessEngineConfigurator} instances are used, they are first
   * ordered by this priority number (lowest to highest).
   * If you have dependencies between {@link ProcessEngineConfigurator}
   * instances, use the priorities accordingly to order them as needed.
   */
  int getPriority();
 
}


ProcessEngineConfigurator类图关系如下:

 

 

上面的类图AbstractProcessEngineConfigurator类实现了ProcessEngineConfigurator接口,AbstractProcessEngineConfigurator是一个抽象类,所以我们使用的时候继承AbstractProcessEngineConfigurator类复写里面的方法即可(模板方法)

上面我们自定义的类MyProcessEngineConfigurator1中的方法

public void beforeInit(

ProcessEngineConfigurationImplprocessEngineConfiguration) {

System.out.println("1111111111111");

}

 

public void configure(

ProcessEngineConfigurationImplprocessEngineConfiguration) {

}

我们可以拿到ProcessEngineConfigurationImpl这个对象其实就是StandaloneProcessEngineConfiguration的父类,里面有很多的属性我们就可以修改了。

怎么修改呢?只要拿到这个对象我们就很方便修改了。

具体的修改如下:

//伪代码 加载jdbc.properties文件 获取配置的值,进行解密然后设置进去 解密算法后续讲解,当然懂的话可以自己直接修改。

descJdbc(ProperUtils.load());

processEngineConfiguration.setJdbcDriver(jdbcDriver);

processEngineConfiguration.setJdbcPassword(jdbcPassword);

processEngineConfiguration.setJdbcUrl(jdbcUrl);

processEngineConfiguration.setJdbcUsername(jdbcUsername)

 

上面提到的引擎初始化完毕会调用configure()中的方法,所以这里可以自定义实现的功能即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值