我们在使用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. Luogu 3690 Link Cut Tree

    Luogu 3690 Link Cut Tree \(LCT\) 模板题.可以参考讲解和这份码风(个人认为)良好的代码. 注意用 \(set\) 来维护实际图中两点是否有直接连边,否则无脑 \(Lin ...

  2. python(三):函数

    一.函数.名称空间与作用域 1.函数的构成 python有三种层次的抽象:(1)程序可分成多个模块:(2)每个模块包含多条语句:(3)每条语句对对象进行操作.函数大致处于第二层.函数有它的定义格式.参 ...

  3. MYSQL在当前日期的基础上加上N(年月日分秒)

    //把id为1的那条数据的开始时间改为现在  结束时间改为开始时间的1个月后 update 表明 set  begintime=now(),endtime=date_add(NOW(), interv ...

  4. python正则的使用

    python的正则是通过re模块的支持 匹配的3个函数 match :只从字符串的开始与正则表达式匹配,匹配成功返回matchobject,否则返回none: re.match(pattern, st ...

  5. uuid 了解

    什么是UUID? UUID是Universally Unique Identifier的缩写,它是在一定的范围内(从特定的名字空间到全球)唯一的机器生成的标识符.UUID具有以下涵义: 经由一定的算法 ...

  6. 最短路径问题的Dijkstra算法

      问题 最短路径问题的Dijkstra算法 是由荷兰计算机科学家艾兹赫尔·戴克斯特拉提出.迪科斯彻算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法终于得到一个最短路径树>    ...

  7. 常见企业IT支撑【4、gitlab代码管理工具】

    安装方式可借鉴http://www.cnblogs.com/juandx/p/5339254.html 安装方式

  8. licode从客户端到连上信令服务器流程

    var config = {audio: true, video: true, data: true, screen: screen, videoSize: [640, 480, 640, 480], ...

  9. NGINX conf 配置文件中的变量大全 可用变量列表及说明

    $args #这个变量等于请求行中的参数.$content_length #请求头中的Content-length字段.$content_type #请求头中的Content-Type字段.$docu ...

  10. java web 程序---刷新页面次数进一步

    <%@ page language="java" import="java.util.*" pageEncoding="gb2312" ...