我们在使用JBPM定义流程的时候经常要在流程定义文件中加入一个继承xxxHandler的类来实现我们的业务逻辑判断或者其他的需求,在这个类中一般都是用Spring的Application来获取,而这种情况每次都需要加载配置。

假设使用的Handle类是RoleAssignmentHandler,需要注入的属性石UserService, 以下有几种解决办法:

1、在RoleAssignmentHandler中把UserService声明成static

  1. //@Component
  2. public class RoleAssignmentHandler implements AssignmentHandler {
  3. private static final long serialVersionUID = 1L;
  4. //(注解式的Resource不能用在static修饰的字段)
  5. //@Resource(name="userService")//配置static的userService
  6. private static UserService userService;
  7. public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
  8. userService.getUserById("");//调用userService的方法
  9. }
  10. public void setUserService(UserService userService) {
  11. RoleAssignmentHandler.userService = userService;
  12. }
  13. }

为什么定义成静态的就可以呢?我们都知道静态变量时类级别的变量,所有这个类的实例共享一份,那么第一次Spring给我们创建这个对象的时 候,userService有值了等到第二次JBPM给我们创建这个对象的时候由于UserService是static的,所以他依然会有值 所以通过这种方法我们可以得到UserService对象,但是我们并不推荐这种方法,因为确实有点浪费内存资源 Spring明明已经把这个对象创建好了但是我们却没有去使用这个对象而是去使用了另一个由JBPM给我们创建的一个对象,但这种方法是可行的。

2、自动注入。

首先定义一个类BeanAutowire实现BeanFactoryAware接口,并把这个类交给spring管理。

  1. @Component
  2. public class BeanAutowire implements BeanFactoryAware{
  3. private static  BeanFactory beanFactory;
  4. public BeanAutowire() {
  5. if (null != beanFactory) {
  6. ((AutowireCapableBeanFactory)beanFactory).autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
  7. }
  8. }
  9. public void setBeanFactory(BeanFactory arg0) throws BeansException {
  10. // TODO Auto-generated method stub
  11. BeanAutowire.beanFactory=arg0;
  12. }
  13. }

然后让RoleAssignmentHandler类继承BeanAutowire:

  1. public class RoleAssignmentHandler extends BeanAutowire implements AssignmentHandler {
  2. private static final long serialVersionUID = 1L;
  3. @Resource(name="userService")
  4. private UserService userService;
  5. public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
  6. // TODO Auto-generated method stub
  7. userService.getUserById("");//调用userService的方法
  8. }
  9. public void setUserService(UserService userService) {
  10. RoleAssignmentHandler.userService = userService;
  11. }
  12. }

这样,在spring初始化的时候会把BeanFactory注入到BeanAutowire中去,在jbpm每次使用Handle类时候会new一个Handle的实例,这时候会首先调用父类的构造方法:

  1. public BeanAutowire() {
  2. if (null != beanFactory) {
  3. ((AutowireCapableBeanFactory)beanFactory).autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
  4. }
  5. }

把需要注入的对象注入到Handle类的实例中去。

3、参考springmodules.jar的方法

我们先借鉴一下JbpmHandlerProxy这个类是怎么拿到Beanfactory对象的。我们要关联上源代码了解一下他的运行机制: 
JbpmHandlerProxy的运行机制: 
jbpmhandlerProxy通过一个JbpmFactoryLocator来得到一个Beanfactory对象,那么他是怎么得到的呢,jbpmfactoryLocator实现了一个BeanFactoryAwre接口,所以有个 
setBeanfacotry(BeanFactory factory) 方法,那么是哪个类来调用的这个方法 呢?是LocalJbpmConfigurationFactoryBean他也实现了BeanFactoryAwre接口所以他也有一个 
setBeanfacotry(BeanFactory factory) 方法,因为这个类的对象我们是让spring帮我们生成的,所以在tomcat启动的时候spring会把Beanfactory对象放作为参数传递给 
LocalJbpmConfigurationFactoryBean实现的setBeanfacotry(BeanFactory factory) 中,然后再这个方法中LocalJbpmConfigurationFactoryBean又去调用jbpmfactoryLocator 
类的setBeanfacotry(BeanFactory factory) 关键就在这里,JbpmFactoryLocator中有一个protected static BeanFactory defaultFactory = null; 他把setFactory方法传递给他的 
Beanfactory对象赋值给了静态变量defaultFactory。 
然后在JbpmHandlerProxy类的retrieveBeanFactory方法中new JbpmFaotoryLocator对象,因为他里面的Beanfactory属性是静态的所以不管你怎么new他都是有值的,然后返回这个值:

  1. protected BeanFactory retrieveBeanFactory() {
  2. BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
  3. BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
  4. if (factory == null)
  5. throw new IllegalArgumentException("no beanFactory found under key=" + null);
  6. try {
  7. return factory.getFactory();
  8. }
  9. finally {
  10. factory.release();
  11. }
  12. }

以下是这个方法的具体实施办法:

这里,由于springmodules跟jbpm4.4的集成有些问题,所以单独把JbpmFactoryLocator这个类拿了出来,修改一下相关类的引入就可以使用:

  1. /**
  2. * Created on Jan 24, 2006
  3. *
  4. * $Id: JbpmFactoryLocator.java,v 1.3 2006-12-06 14:13:18 costin Exp $
  5. * $Revision: 1.3 $
  6. */
  7. package com.founder.jbpm.util;
  8. import java.util.ArrayList;
  9. import java.util.HashMap;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import java.util.Map;
  13. import org.apache.commons.logging.Log;
  14. import org.apache.commons.logging.LogFactory;
  15. import org.springframework.beans.BeansException;
  16. import org.springframework.beans.FatalBeanException;
  17. import org.springframework.beans.factory.BeanFactory;
  18. import org.springframework.beans.factory.BeanFactoryAware;
  19. import org.springframework.beans.factory.BeanNameAware;
  20. import org.springframework.beans.factory.access.BeanFactoryLocator;
  21. import org.springframework.beans.factory.access.BeanFactoryReference;
  22. /**
  23. * BeanFactoryLocator used for injecting Spring application context into JBPM.
  24. * The difference/advantage over the traditional SingletonBeanFactoryLocator is
  25. * that it does not parse a bean factory definition; it is used internally by
  26. * the jbpmSessionFactoryBean and it will register the bean factory/application
  27. * context containing it automatically under the name and and aliases of the
  28. * bean. If there is only one BeanFactory registered then a null value can be
  29. * used with setBeanName method. <p/> Note that in most cases, you don't have to
  30. * use this class directly since it is used internally by
  31. * LocalJbpmConfigurationFactoryBean.
  32. *
  33. * @author Costin Leau
  34. *
  35. */
  36. public class JbpmFactoryLocator implements BeanFactoryLocator, BeanFactoryAware, BeanNameAware {
  37. private static final Log logger = LogFactory.getLog(JbpmFactoryLocator.class);
  38. // default factory name (for nested classes)
  39. private String factoryName = JbpmFactoryLocator.class.getName();
  40. // alias/bean name to BeanFactory
  41. protected static final Map<String, BeanFactory> beanFactories = new HashMap<String, BeanFactory>();
  42. // beanfactory to alias/bean name map
  43. protected static final Map<BeanFactory,List<String>> beanFactoriesNames = new HashMap<BeanFactory, List<String>>();
  44. protected static final Map<BeanFactory, Integer> referenceCounter = new HashMap<BeanFactory, Integer>();
  45. protected static boolean canUseDefaultBeanFactory = true;
  46. protected static BeanFactory defaultFactory = null;
  47. /**
  48. * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
  49. */
  50. public void setBeanFactory(final BeanFactory beanFactory) throws BeansException {
  51. // add the factory as default if possible (if it's the only one)
  52. synchronized (JbpmFactoryLocator.class) {
  53. if (canUseDefaultBeanFactory) {
  54. if (defaultFactory == null) {
  55. defaultFactory = beanFactory;
  56. if (logger.isDebugEnabled())
  57. logger.debug("default beanFactoryReference=" + defaultFactory);
  58. }
  59. else {
  60. if (logger.isDebugEnabled())
  61. logger.debug("more then one beanFactory - default not possible to determine");
  62. canUseDefaultBeanFactory = false;
  63. defaultFactory = null;
  64. }
  65. }
  66. }
  67. // add name
  68. addToMap(factoryName, beanFactory);
  69. Integer counter = (Integer) referenceCounter.get(beanFactory);
  70. if (counter == null)
  71. referenceCounter.put(beanFactory, new Integer(0));
  72. // add aliases
  73. String[] aliases = beanFactory.getAliases(factoryName);
  74. List<String> names = new ArrayList<String>(1 + aliases.length);
  75. names.add(factoryName);
  76. for (int i = 0; i < aliases.length; i++) {
  77. addToMap(aliases[i], beanFactory);
  78. names.add(aliases[i]);
  79. }
  80. // append previous found names
  81. List<String> previousNames = (List<String>) beanFactoriesNames.get(beanFactory);
  82. if (previousNames != null)
  83. names.addAll(previousNames);
  84. beanFactoriesNames.put(beanFactory, names);
  85. }
  86. protected void addToMap(String fName, BeanFactory factory) {
  87. if (logger.isDebugEnabled())
  88. logger.debug("adding key=" + fName + " w/ reference=" + factory);
  89. synchronized (beanFactories) {
  90. // override check
  91. if (beanFactories.containsKey(fName))
  92. throw new IllegalArgumentException("a beanFactoryReference already exists for key " + factoryName);
  93. beanFactories.put(fName, factory);
  94. }
  95. }
  96. protected void removeReference(BeanFactory factory) {
  97. synchronized (referenceCounter) {
  98. Integer count = (Integer) referenceCounter.get(factory);
  99. // decrement counter
  100. int counter = count.intValue();
  101. counter--;
  102. if (counter == 0) {
  103. if (logger.isDebugEnabled())
  104. logger.debug("removing factory references under key " + factoryName);
  105. referenceCounter.remove(factory);
  106. // reset also default beanFactory
  107. if (referenceCounter.isEmpty()) {
  108. canUseDefaultBeanFactory = true;
  109. defaultFactory = null;
  110. }
  111. List<String> names = (List<String>) beanFactoriesNames.get(factory);
  112. beanFactoriesNames.remove(factory);
  113. synchronized (beanFactories) {
  114. for (Iterator iter = names.iterator(); iter.hasNext();) {
  115. beanFactories.remove(iter.next());
  116. }
  117. }
  118. }
  119. else
  120. referenceCounter.put(factory, new Integer(counter));
  121. }
  122. }
  123. /**
  124. * @see org.springframework.beans.factory.access.BeanFactoryLocator#useBeanFactory(java.lang.String)
  125. */
  126. public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException {
  127. // see if there is a default FactoryBean
  128. BeanFactory factory;
  129. if (factoryKey == null) {
  130. if (!canUseDefaultBeanFactory)
  131. throw new IllegalArgumentException(
  132. "a non-null factoryKey needs to be specified as there are more then one factoryKeys available ");
  133. factory = defaultFactory;
  134. }
  135. else {
  136. factory = (BeanFactory) beanFactories.get(factoryKey);
  137. if (factory == null)
  138. throw new IllegalArgumentException("there is no beanFactory under key " + factoryKey);
  139. }
  140. // increment counter
  141. synchronized (referenceCounter) {
  142. Integer counter = (Integer) referenceCounter.get(factory);
  143. referenceCounter.put(factory, new Integer(counter.intValue() + 1));
  144. }
  145. final BeanFactory finalFactory = factory;
  146. // simple implementation
  147. return new BeanFactoryReference() {
  148. private BeanFactory fact = finalFactory;
  149. public BeanFactory getFactory() {
  150. if (this.fact == null)
  151. throw new IllegalArgumentException("beanFactory already released");
  152. return this.fact;
  153. }
  154. public void release() throws FatalBeanException {
  155. if (fact != null) {
  156. removeReference(fact);
  157. // remove the factory reference
  158. this.fact = null;
  159. }
  160. }
  161. };
  162. }
  163. /**
  164. * @see org.springframework.beans.factory.BeanNameAware#setTargetBean(java.lang.String)
  165. */
  166. public void setBeanName(String name) {
  167. factoryName = name;
  168. }
  169. }

把这个类配置成spring的bean:

  1. <bean id="baseAutowire" class="com.founder.jbpm.util.JbpmFactoryLocator">
  2. </bean>

定义一个类BaseAutowire:

  1. package com.founder.jbpm.util;
  2. import org.springframework.beans.factory.BeanFactory;
  3. import org.springframework.beans.factory.access.BeanFactoryLocator;
  4. import org.springframework.beans.factory.access.BeanFactoryReference;
  5. import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
  6. public class BaseAutowire {
  7. //arg1:向哪个类进行属性注入
  8. //arg2:按照那种方式注入:按类型、或者名称....此处按照类型
  9. //arg2:是否检查依赖关系,一般情况下为true要检查依赖关系。
  10. public BaseAutowire() {
  11. ((AutowireCapableBeanFactory)retrieveBeanFactory())
  12. .autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
  13. }
  14. protected BeanFactory retrieveBeanFactory() {
  15. BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
  16. BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
  17. if (factory == null)
  18. throw new IllegalArgumentException("no beanFactory found under key=" + null);
  19. try {
  20. return factory.getFactory();
  21. }
  22. finally {
  23. factory.release();
  24. }
  25. }
  26. }

让RoleAssignmentHandler继承BaseAutowire即可:

  1. public class RoleAssignmentHandler extends BaseAutowire implements AssignmentHandler {
  2. private static final long serialVersionUID = 1L;
  3. private  UserService userService;
  4. public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
  5. // TODO Auto-generated method stub
  6. userService.getUserById("");//调用userService的方法
  7. }
  8. public ProcessEngine getProcessEngine() {
  9. return processEngine;
  10. }
  11. public void setProcessEngine(ProcessEngine processEngine) {
  12. this.processEngine = processEngine;
  13. }
  14. }

在JBPM的Handle类中调用Spring管理的类的更多相关文章

  1. 170630、springboot编程之普通类中调用spring管理的bean对象

    我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,想直接使用 ...

  2. 在普通类中获取Spring管理的bean

    1.在项目中添加下面的类: import org.springframework.context.ApplicationContext; import org.springframework.cont ...

  3. tomcat启动后,在普通java类中获取spring管理的bean和ServletContext,(经过验证,可以取到)

    //从spring容易中获取bean public static Object getBean(String beanName){ ApplicationContext context = Conte ...

  4. Servlet中获取Spring管理的bean

    描述: 在Servlet中调用Spring管理的接口,可以使Dao/Service/ServiceImpl. 前提是在调用的bean中有注解: @Repository("beanName&q ...

  5. Spring MVC普通类或工具类中调用service报空空指针的解决办法(调用service报java.lang.NullPointerException)

    当我们在非Controller类中应用service的方法是会报空指针,如图: 这是因为Spring MVC普通类或工具类中调用service报空null的解决办法(调用service报java.la ...

  6. springboot 项目中在普通类中调用dao层的mapper 出现空指针异常

    项目中我遇到同样的问题 特记载一下 有两种方式 一. 该类使用@Component注解 添加一个本类类型的静态字段 创建一个初始化方法,贴上@PostConstruct 标签,用于注入bean 创建方 ...

  7. spring管理的类如何调用非spring管理的类

    spring管理的类如何调用非spring管理的类. 就是使用一个spring提供的感知概念,在容器启动的时候,注入上下文即可. 下面是一个工具类. import org.springframewor ...

  8. C#在派生类中调用基类成员

    一.在派生类中调用基类成员 在C#的派生类中,我们可以使用base关键字调用基类中的公有或者受保护成员.这些成员只能是构造函数.实例方法或者实例属性. base关键字调用基类成员的语法格式如下: ba ...

  9. 谈谈java中静态变量与静态方法在有继承关系的两个类中调用

    谈谈java中静态变量与静态方法在有继承关系的两个类中调用 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量和静态方法在有继承关系的两个类中的问题测试 ...

随机推荐

  1. BZOJ1227 SDOI2009 虔诚的墓主人【树状数组+组合数】【好题】*

    BZOJ1227 SDOI2009 虔诚的墓主人 Description 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地. ...

  2. Windows10安装MySQL8.0

    1.到MySQL官网下载安装包:https://dev.mysql.com/downloads/mysql/:选择8.0版本: 2.将下载好的安装包(mysql-8.0.12-winx64 .zip) ...

  3. BW数据加载

    BW数据加载的优先级   1.主数据属性的加载 步骤图  从下到上 1)运行InfoPackage加载到PSA 找到主数据属性的InfoPackage,双击  点击Start按钮  点击监视器,查看运 ...

  4. matplotlib ----- 初步

    直接看几段代码即可: # 加载模块的方式 import matplotlib.pyplot as plt import numpy as np # 最简单的单线图 x = np.linspace(0, ...

  5. 从数据库导出数据到excel之List<map>导出

    说明:很多时候取出来的数据是封装为List<Map<String,Object>>,可以直接导出excel表格 项目说明就在 “上一篇” 直接上代码(数据层和业务层不用说了,查 ...

  6. Quick 3.3 final 加载ccs的变化

    1,用self._topUIWidget = ccs.GUIReader:getInstance():widgetFromJsonFile("mapTopUI.json")就还是用 ...

  7. Eclipse git插件使用

    1.Eclipse git插件使用 1)配置提交用户名和邮箱 2)在eclipse中选择Show View 搜索git 3)点击clone按钮 选择代码保存路径 4)导入项目 5)git插件功能介绍 ...

  8. Python——你应该知道这些

    1. Python的出生 1989年 Guido van Rossum开始编写Python语言编辑器(龟叔为了打发无聊的圣诞节) 1991年 第一个Python编译器诞生(正式诞生) 1994年 Py ...

  9. RK3288 增加双屏异显 eDP+LVDS

    CPU:RK3288 系统:Android 5.1 下面是官方文档中的信息. 1.rk3288 支持的显示接口可以任意组合. 2.双屏异显时,一个显示接口当主屏,另一个当副屏:主副屏由板级 dts 文 ...

  10. 贴几个erlang文档站点

    国外三方的文档,比较全, http://erldocs.com/ 这个貌似是国内的版本,不是很新 http://erldoc.com/ 国内dhq大神的,也不是很新 http://dhq.me/erl ...