我们在使用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. Python学习-购物车程序

    程序:购物车程序 需求: 启动程序后,让用户输入工资,然后打印商品列表 允许用户根据商品编号购买商品 用户选择商品后,检测余额是否够,够就直接扣款,不够就提醒 可随时退出,退出时,打印已购买商品和余额 ...

  2. groovy && java 混编 gradle 配置

    参考配置: apply plugin: "application" apply plugin: "java" apply plugin: "groov ...

  3. F4NNIU 版本的标准电阻列表(2018-09-29 更新)

    F4NNIU 版本的标准电阻列表(2018-09-29 更新) 值代码 电阻值 格式化值 单位 公差代码 公差 格式化值数字 描述 0RJ 0 0 R J 5% J0000 0R 5% (0RJ) 1 ...

  4. 谈谈JS中的高级函数

    博客原文地址:Claiyre的个人博客如需转载,请在文章开头注明原文地址 在JavaScript中,函数的功能十分强大.它们是第一类对象,也可以作为另一个对象的方法,还可以作为参数传入另一个函数,不仅 ...

  5. ubuntu15.10下code::blocks设置运行窗口为gnome命令行

    code::blocks编译运行C++程序(F9)默认出现的运行串口在有鼠标的情况下进行粘贴还是很方便的,只要按下鼠标滑轮,位与剪切板中的数据就能粘贴到运行串口中. 但是对于用笔记本而且没有鼠标地童鞋 ...

  6. jdk1.8新特性之lambda表达式

    lambda表达式其实就是指一个匿名函数,应用最广泛的就是匿名内部类的简化.在jdk1.8之前,我们定义一个匿名内部类可能需要写一大坨代码,现在有了lambda之后,可以写的很简洁了.但不是说lamb ...

  7. Eclipse Failed to load D:\android-sdk-windows\build-tools\27.0.3\lib\dx.jar

    Failed to load D:\android-sdk-windows\build-tools\27.0.3\lib\dx.jar Unknown error: Unable to build: ...

  8. javascript基础-js对象

    一.js对象的创建 1.普通最简单的方式 var teacher = new Object( ); teacher.name = "zhangsan"; teacher.age = ...

  9. RandomStringUtils工具类(java随机生成字符串)

    使用RandomStringUtils可以选择生成随机字符串,可以是全字母,全数字,自定义生成字符等等... 其最基础的方法: 参数解读: count:需要生成的随机串位数 letters:只要字母 ...

  10. vptr, vtable, virtual base class table

    #include <iostream> using namespace std; class X { int x, y, z; }; class Y: public virtual X { ...