`

在JBPM的Handle类中调用Spring管理的类

阅读更多

      我们在使用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

    2. **项目源代码(全,不含jar包).rar**:这可能是一个完整的JBPM项目源代码,包含了流程定义、服务实现、配置文件等,用于展示如何在实际项目中使用JBPM和Spring进行流程管理。 3. **sql.rar**:这个压缩包可能...

    jbpm+spring配置

    在Spring中,你需要配置一个数据源,并确保jbpm能使用这个数据源。这可以通过Spring的`DataSource`bean来完成。 3. **创建jbpm的工作空间和部署单元**:jbpm的流程定义(即bpmn2模型文件)需要部署到工作空间中。在...

    jbpm4.3与spring整合

    在企业级应用开发中,流程管理引擎JBPM(JBoss Business Process Management)与Spring框架的结合使用是常见的一种技术方案。JBPM是一个灵活、强大的业务流程管理工具,而Spring框架则以其优秀的依赖注入(DI)和...

    JBPM4.3 Spring会签 实例

    总之,这个JBPM4.3与Spring的会签实例展示了如何在企业级应用中有效地管理和控制业务流程。通过学习和实践这样的实例,开发者能够掌握如何利用这两个强大的工具集,设计和实现符合业务需求的高效流程管理系统。

    jbpm4 集成 spring 的试用代码

    将jbpm4集成到Spring中,可以充分利用Spring的管理优势,提高流程服务的可测试性和可配置性。 在“jbpm4 集成 spring”的场景中,我们需要关注以下几个关键知识点: 1. **集成配置**:首先,我们需要在Spring的...

    jbpm4整合struts2+spring2.5+hibernate3.3

    在Spring中配置jbpm4,主要涉及以下几点: 1. 配置jbpm的数据源,使其与Hibernate共用,以确保事务的一致性。 2. 注册jbpm的SessionFactory,使Spring能够管理SessionFactory的生命周期。 3. 配置jbpm的JobExecutor...

    Jbpm4.4 整合Spring Hibernate4

    在Jbpm4.4中整合Spring,可以利用Spring的这些优势,比如将Jbpm的流程实例管理、任务分配等操作集成到Spring容器中,实现流程服务的声明式配置和管理。 **3. Hibernate4整合** Hibernate4是流行的ORM(对象关系映射...

    jBPM4与Spring整合的2种方式

    1. **事务边界**:在Spring中,确保jBPM4的操作与数据库操作处于同一事务范围内,以保证数据一致性。 2. **日志和异常处理**:利用Spring的日志管理和AOP切面,对jBPM4的异常进行统一处理,提高系统的健壮性。 3. **...

    JBPM环境搭建步骤+spring+mybatis

    文档是原创,本人从网络上获取了前辈很多知识,觉着有义务反馈给网络,如果觉着文档没用或资源分要的太多,请不要乱喷,毕竟西辛辛苦苦占用工作时间写的,并不是要那点分,只不过想体现一下文档的价值

    JBPM4.4+spring+ext整合

    - **工作流接口**:在EXT界面中,通过Ajax调用Spring服务来启动流程、分配任务、完成任务等。 - **异常处理**:设置合适的异常处理机制,确保前端能正确处理后端可能出现的问题。 通过JBPM4.4、Spring和EXT的整合...

    spring2_struts2_jbpm3.2.rar_jbpm struts2_jbpm-demo_jbpm3 spring_

    在Spring中,我们可以创建一个Service Bean来调用JBPM的工作流API,处理流程的启动、暂停、继续和结束等操作。同时,Struts2的动作类可以通过Spring的代理访问这些Service Bean,从而在用户交互时触发流程的执行。...

    jbpm4.4 ibatis-spring 整合

    jbpm4.4 ibatis-spring 整合

    jbpm5.4 spring mvc 集成

    - **jbpm配置**:需要在Spring配置文件中定义jbpm的数据源、事务管理器、流程引擎工厂等bean。 - **Spring MVC配置**:配置DispatcherServlet、视图解析器、模型-视图映射等,同时设置jbpm相关bean的事务属性。 -...

    spring与JBPM整合ppt

    8. **实战案例**:PPT可能会包含一些实际项目中的整合示例,展示如何在Spring应用中定义、启动和管理JBPM流程,以及如何处理流程中的事件和决策。 9. **最佳实践**:整合过程中需要注意的问题,如性能优化、错误...

    jbpm4.0实例(整合spring2.5+ext3.0+hibernate)

    jbpm4.0实例(整合spring2.5+ext3.0+hibernate)

    jbpm4.3-spring2.5整合

    Jbpm的库文件(如jbpm-jpdl.jar, jbpm-runtime.jar等)需要添加到项目的类路径中,同时Spring的相关库(如spring-core.jar, spring-context.jar, spring-tx.jar等)也不能少。 整合步骤通常包括以下部分: 1. **...

    struts2+spring+hibernate+jbpm工作流实例

    此外,Spring还提供了对Jbpm的工作流服务的整合,使得在业务流程中调用工作流变得简单。 Hibernate是一个持久化框架,它简化了数据库操作,通过对象关系映射(ORM)将Java对象与数据库表进行对应。在公文审批流程中...

    提前试用spring 集成 jbpm4

    将jbpm4集成到Spring中,可以实现灵活的业务流程自动化,提高开发效率。 在"提前试用spring 集成 jbpm4"这个主题中,我们主要关注的是如何将这两个强大的工具结合在一起,以实现更高效、更灵活的业务流程控制。首先...

    spring-modules-jbpm31-0.6.jar

    spring-modules-jbpm31-0.6.jar,spring整合jbpm的jar包

Global site tag (gtag.js) - Google Analytics