我们在使用JBPM定义流程的时候经常要在流程定义文件中加入一个继承xxxHandler的类来实现我们的业务逻辑判断或者其他的需求,在这个类中一般都是用Spring的Application来获取,而这种情况每次都需要加载配置。
假设使用的Handle类是RoleAssignmentHandler,需要注入的属性石UserService, 以下有几种解决办法:
1、在RoleAssignmentHandler中把UserService声明成static
//@Component
public class RoleAssignmentHandler implements AssignmentHandler {
private static final long serialVersionUID = 1L;
//(注解式的Resource不能用在static修饰的字段)
//@Resource(name="userService")//配置static的userService
private static UserService userService;
public void assign(Assignable arg0, OpenExecution arg1) throws Exception {
userService.getUserById("");//调用userService的方法
}
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 {
// TODO Auto-generated method stub
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 {
// TODO Auto-generated method stub
userService.getUserById("");//调用userService的方法
}
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这个类拿了出来,修改一下相关类的引入就可以使用:
/**
* Created on Jan 24, 2006
*
* $Id: JbpmFactoryLocator.java,v 1.3 2006-12-06 14:13:18 costin Exp $
* $Revision: 1.3 $
*/
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;
/**
* BeanFactoryLocator used for injecting Spring application context into JBPM.
* The difference/advantage over the traditional SingletonBeanFactoryLocator is
* that it does not parse a bean factory definition; it is used internally by
* the jbpmSessionFactoryBean and it will register the bean factory/application
* context containing it automatically under the name and and aliases of the
* bean. If there is only one BeanFactory registered then a null value can be
* used with setBeanName method. <p/> Note that in most cases, you don't have to
* use this class directly since it is used internally by
* LocalJbpmConfigurationFactoryBean.
*
* @author Costin Leau
*
*/
public class JbpmFactoryLocator implements BeanFactoryLocator, BeanFactoryAware, BeanNameAware {
private static final Log logger = LogFactory.getLog(JbpmFactoryLocator.class);
// default factory name (for nested classes)
private String factoryName = JbpmFactoryLocator.class.getName();
// alias/bean name to BeanFactory
protected static final Map<String, BeanFactory> beanFactories = new HashMap<String, BeanFactory>();
// beanfactory to alias/bean name map
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;
/**
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
public void setBeanFactory(final BeanFactory beanFactory) throws BeansException {
// add the factory as default if possible (if it's the only one)
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;
}
}
}
// add name
addToMap(factoryName, beanFactory);
Integer counter = (Integer) referenceCounter.get(beanFactory);
if (counter == null)
referenceCounter.put(beanFactory, new Integer(0));
// add aliases
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]);
}
// append previous found names
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) {
// override check
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);
// decrement counter
int counter = count.intValue();
counter--;
if (counter == 0) {
if (logger.isDebugEnabled())
logger.debug("removing factory references under key " + factoryName);
referenceCounter.remove(factory);
// reset also default beanFactory
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));
}
}
/**
* @see org.springframework.beans.factory.access.BeanFactoryLocator#useBeanFactory(java.lang.String)
*/
public BeanFactoryReference useBeanFactory(String factoryKey) throws BeansException {
// see if there is a default FactoryBean
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);
}
// increment counter
synchronized (referenceCounter) {
Integer counter = (Integer) referenceCounter.get(factory);
referenceCounter.put(factory, new Integer(counter.intValue() + 1));
}
final BeanFactory finalFactory = factory;
// simple implementation
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);
// remove the factory reference
this.fact = null;
}
}
};
}
/**
* @see org.springframework.beans.factory.BeanNameAware#setTargetBean(java.lang.String)
*/
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 {
//arg1:向哪个类进行属性注入
//arg2:按照那种方式注入:按类型、或者名称....此处按照类型
//arg2:是否检查依赖关系,一般情况下为true要检查依赖关系。
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 {
// TODO Auto-generated method stub
userService.getUserById("");//调用userService的方法
}
public ProcessEngine getProcessEngine() {
return processEngine;
}
public void setProcessEngine(ProcessEngine processEngine) {
this.processEngine = processEngine;
}
}
分享到:
相关推荐
JBPM使用实例,sql spring 配合http://blog.csdn.net/myjava_024/archive/2008/12/13/3510752.aspx
jbpm4.3与spring整合的一个小文档
jbpm4.4 ibatis-spring 整合
jbpm4.0实例(整合spring2.5+ext3.0+hibernate)
文档是原创,本人从网络上获取了前辈很多知识,觉着有义务反馈给网络,如果觉着文档没用或资源分要的太多,请不要乱喷,毕竟西辛辛苦苦占用工作时间写的,并不是要那点分,只不过想体现一下文档的价值
jbpm4 集成 spring 的试用代码 spring2.5 hibernate3.3 jbpm4 beta1 后的svn版本
JBPM4.3与Spring会签 实例,欢迎交流ningjinlin@gmail.com
spring与jbpm的集成包(符集成方法)
spring+jbpm的配置示例,jbpm配置,希望大家一起进行学习,共同提高
近期网上有人介绍jBPM4与Spring整合的2种方式,但没有人贴出代码,闲着无聊写了个例子,源码见附件,在WEBLOGIC下运行正常,事务由spring控制http://ip:7001/Spring/helloWorld.do
JBPM4.4+spring+ext整合
在学习jbpm5的过程中,发现很难找到一个合适的,能跑的起来的,整合ssh的例子,之前在csdn上花费不少分下了好多个,能跑起来的好像就1个,不是jar包不匹配就是些其他的莫名奇妙的错误,对应刚刚接触jbpm的人来说,一...
spring-modules-jbpm30.jar spring-modules-jbpm30.jar
JBPM+STRUTS+SPRING整合
jbpm 4.3 与 spring 集成
spring-modules-jbpm31-0.6.jar,spring整合jbpm的jar包
风中叶老师讲的JBPM4与Spring整合例子代码 JBPM4 Spring OA工作流系统
Jbpm4.4+hibernate3.5.4+spring3.0.4+struts2.1.8整合 超级详细的文档,透彻讲解JBPM与SSH的整合过程
Spring与JBoss JBPM工作流集成开发指南
jbpm4整合struts2+spring2.5+hibernate3.3.doc