我们在使用JBPM定义流程的时候经常要在流程定义文件中加入一个继承xxxHandler的类来实现我们的业务逻辑判断或者其他的需求,在这个类中一般都是用Spring的Application来获取,而这种情况每次都需要加载配置。
假设使用的Handle类是RoleAssignmentHandler,需要注入的属性石UserService, 以下有几种解决办法:
1、在RoleAssignmentHandler中把UserService声明成static
- public class RoleAssignmentHandler implements AssignmentHandler {
-
- private static final long serialVersionUID = 1L;
-
-
-
- private static UserService userService;
-
- public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
-
- userService.getUserById("");
- }
-
- public void setUserService(UserService userService) {
-
- RoleAssignmentHandler.userService = userService;
- }
-
- }
为什么定义成静态的就可以呢?我们都知道静态变量时类级别的变量,所有这个类的实例共享一份,那么第一次Spring给我们创建这个对象的时 候,userService有值了等到第二次JBPM给我们创建这个对象的时候由于UserService是static的,所以他依然会有值 所以通过这种方法我们可以得到UserService对象,但是我们并不推荐这种方法,因为确实有点浪费内存资源 Spring明明已经把这个对象创建好了但是我们却没有去使用这个对象而是去使用了另一个由JBPM给我们创建的一个对象,但这种方法是可行的。
2、自动注入。
首先定义一个类BeanAutowire实现BeanFactoryAware接口,并把这个类交给spring管理。
- @Component
-
-
- public class BeanAutowire implements BeanFactoryAware{
-
- private static BeanFactory beanFactory;
-
- public BeanAutowire() {
-
- if (null != beanFactory) {
-
- ((AutowireCapableBeanFactory)beanFactory).autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
-
- }
-
- }
-
- public void setBeanFactory(BeanFactory arg0) throws BeansException {
-
-
-
- BeanAutowire.beanFactory=arg0;
-
- }
-
- }
然后让RoleAssignmentHandler类继承BeanAutowire:
- public class RoleAssignmentHandler extends BeanAutowire implements AssignmentHandler {
-
- private static final long serialVersionUID = 1L;
-
- @Resource(name="userService")
-
- private UserService userService;
-
- public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
-
-
-
-
-
- userService.getUserById("");
-
-
- }
-
- public void setUserService(UserService userService) {
-
-
- RoleAssignmentHandler.userService = userService;
-
-
- }
- }
这样,在spring初始化的时候会把BeanFactory注入到BeanAutowire中去,在jbpm每次使用Handle类时候会new一个Handle的实例,这时候会首先调用父类的构造方法:
- public BeanAutowire() {
-
- if (null != beanFactory) {
-
- ((AutowireCapableBeanFactory)beanFactory).autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME, true);
-
- }
-
- }
把需要注入的对象注入到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他都是有值的,然后返回这个值:
- protected BeanFactory retrieveBeanFactory() {
- BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
- BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
- if (factory == null)
- throw new IllegalArgumentException("no beanFactory found under key=" + null);
-
- try {
- return factory.getFactory();
- }
- finally {
- factory.release();
- }
- }
以下是这个方法的具体实施办法:
这里,由于springmodules跟jbpm4.4的集成有些问题,所以单独把JbpmFactoryLocator这个类拿了出来,修改一下相关类的引入就可以使用:
- package com.founder.jbpm.util;
-
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.FatalBeanException;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.BeanFactoryAware;
- import org.springframework.beans.factory.BeanNameAware;
- import org.springframework.beans.factory.access.BeanFactoryLocator;
- import org.springframework.beans.factory.access.BeanFactoryReference;
-
- public class JbpmFactoryLocator implements BeanFactoryLocator, BeanFactoryAware, BeanNameAware {
-
- private static final Log logger = LogFactory.getLog(JbpmFactoryLocator.class);
-
-
- private String factoryName = JbpmFactoryLocator.class.getName();
-
-
- protected static final Map<String, BeanFactory> beanFactories = new HashMap<String, BeanFactory>();
-
-
- protected static final Map<BeanFactory,List<String>> beanFactoriesNames = new HashMap<BeanFactory, List<String>>();
-
- protected static final Map<BeanFactory, Integer> referenceCounter = new HashMap<BeanFactory, Integer>();
-
- protected static boolean canUseDefaultBeanFactory = true;
-
- protected static BeanFactory defaultFactory = null;
-
-
- public void setBeanFactory(final BeanFactory beanFactory) throws BeansException {
-
-
- synchronized (JbpmFactoryLocator.class) {
- if (canUseDefaultBeanFactory) {
- if (defaultFactory == null) {
- defaultFactory = beanFactory;
- if (logger.isDebugEnabled())
- logger.debug("default beanFactoryReference=" + defaultFactory);
- }
- else {
- if (logger.isDebugEnabled())
- logger.debug("more then one beanFactory - default not possible to determine");
- canUseDefaultBeanFactory = false;
- defaultFactory = null;
- }
- }
- }
-
-
- addToMap(factoryName, beanFactory);
- Integer counter = (Integer) referenceCounter.get(beanFactory);
-
- if (counter == null)
- referenceCounter.put(beanFactory, new Integer(0));
-
-
- String[] aliases = beanFactory.getAliases(factoryName);
- List<String> names = new ArrayList<String>(1 + aliases.length);
- names.add(factoryName);
-
- for (int i = 0; i < aliases.length; i++) {
- addToMap(aliases[i], beanFactory);
- names.add(aliases[i]);
- }
-
-
- List<String> previousNames = (List<String>) beanFactoriesNames.get(beanFactory);
- if (previousNames != null)
- names.addAll(previousNames);
-
- beanFactoriesNames.put(beanFactory, names);
-
- }
-
- protected void addToMap(String fName, BeanFactory factory) {
- if (logger.isDebugEnabled())
- logger.debug("adding key=" + fName + " w/ reference=" + factory);
-
- synchronized (beanFactories) {
-
- if (beanFactories.containsKey(fName))
- throw new IllegalArgumentException("a beanFactoryReference already exists for key " + factoryName);
- beanFactories.put(fName, factory);
- }
- }
-
- protected void removeReference(BeanFactory factory) {
- synchronized (referenceCounter) {
- Integer count = (Integer) referenceCounter.get(factory);
-
- int counter = count.intValue();
- counter--;
- if (counter == 0) {
- if (logger.isDebugEnabled())
- logger.debug("removing factory references under key " + factoryName);
- referenceCounter.remove(factory);
-
-
- if (referenceCounter.isEmpty()) {
- canUseDefaultBeanFactory = true;
- defaultFactory = null;
- }
- List<String> names = (List<String>) beanFactoriesNames.get(factory);
- beanFactoriesNames.remove(factory);
-
- synchronized (beanFactories) {
- for (Iterator iter = names.iterator(); iter.hasNext();) {
- beanFactories.remove(iter.next());
- }
- }
- }
-
- else
- referenceCounter.put(factory, new Integer(counter));
- }
- }
-
-
- public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException {
-
- BeanFactory factory;
-
- if (factoryKey == null) {
- if (!canUseDefaultBeanFactory)
- throw new IllegalArgumentException(
- "a non-null factoryKey needs to be specified as there are more then one factoryKeys available ");
- factory = defaultFactory;
- }
- else {
- factory = (BeanFactory) beanFactories.get(factoryKey);
- if (factory == null)
- throw new IllegalArgumentException("there is no beanFactory under key " + factoryKey);
- }
-
-
- synchronized (referenceCounter) {
- Integer counter = (Integer) referenceCounter.get(factory);
- referenceCounter.put(factory, new Integer(counter.intValue() + 1));
- }
-
- final BeanFactory finalFactory = factory;
-
-
- return new BeanFactoryReference() {
- private BeanFactory fact = finalFactory;
-
- public BeanFactory getFactory() {
- if (this.fact == null)
- throw new IllegalArgumentException("beanFactory already released");
- return this.fact;
- }
-
- public void release() throws FatalBeanException {
- if (fact != null) {
- removeReference(fact);
-
- this.fact = null;
- }
- }
- };
- }
-
-
- public void setBeanName(String name) {
- factoryName = name;
- }
-
- }
把这个类配置成spring的bean:
- <bean id="baseAutowire" class="com.founder.jbpm.util.JbpmFactoryLocator">
- </bean>
定义一个类BaseAutowire:
- package com.founder.jbpm.util;
-
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.access.BeanFactoryLocator;
- import org.springframework.beans.factory.access.BeanFactoryReference;
- import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
-
- public class BaseAutowire {
-
-
-
-
- public BaseAutowire() {
- ((AutowireCapableBeanFactory)retrieveBeanFactory())
- .autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
- }
-
- protected BeanFactory retrieveBeanFactory() {
- BeanFactoryLocator factoryLocator = new JbpmFactoryLocator();
- BeanFactoryReference factory = factoryLocator.useBeanFactory(null);
- if (factory == null)
- throw new IllegalArgumentException("no beanFactory found under key=" + null);
-
- try {
- return factory.getFactory();
- }
- finally {
- factory.release();
- }
- }
- }
让RoleAssignmentHandler继承BaseAutowire即可:
- public class RoleAssignmentHandler extends BaseAutowire implements AssignmentHandler {
-
- private static final long serialVersionUID = 1L;
-
- private UserService userService;
-
- public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
-
- userService.getUserById("");
- }
-
-
-
- public ProcessEngine getProcessEngine() {
- return processEngine;
- }
-
-
- public void setProcessEngine(ProcessEngine processEngine) {
- this.processEngine = processEngine;
- }
- }
在JBPM的Handle类中调用Spring管理的类
原文:http://www.cnblogs.com/toSeeMyDream/p/4370085.html