应用Spring事务管理的功能可以把一组普通的API转换为支持事务的API.
这个功能的实现是利用spring 事务管理的特性: 同一个事务中,其所有应用访问数据库时只维护了一个connection来访问数据库.
这样我们就能通过判断当前LocalThread上下文环境,来决定Connection是否进行commite(),close()等操作.
我们首先需要构造一个WFConnection类,它实现了Connection接口.WFConnection对象可以通过访问LocalThread上下问环境来判断是否进行commite(),close()等操作.
/** * 能够动态的识别数据库connection请求到底来自wfapi还是工作流系统内部 * 对connection进行调用 */ public class WFSpringConnection implements Connection { private Connection myConnection = null ; private org.apache.commons.logging.Log __log = LogFactory.getFactory().getInstance( this .getClass()); public WFSpringConnection(Connection connection) { myConnection = connection; } public void initProxyConnection(Connection connection) { myConnection = connection; } public void close() throws SQLException { String threadName = Thread.currentThread().getName(); __log.debug( " call WFSpringConnection close() threadName: " + threadName); if ( ! isSpringCall()){ myConnection.close(); } } public void commit() throws SQLException { String threadName = Thread.currentThread().getName(); __log.debug( " call WFSpringConnection commit() threadName: " + threadName); if ( ! isSpringCall()){ myConnection.commit(); } }
/** * 判断当前线程是否被spring管理 * @return true 被spring管理的应用调用 */ public boolean isSpringCall(){ boolean isCall =false; Object o = WFAPIContext.get(WFAPIAspect.WFAPI_THREAD_REQUEST_LABEL); if(o!=null){ String threadLabel = (String)o; if(threadLabel.compareTo(WFAPIAspect.WFAPI_THREAD_REQUEST_LABEL)==0){ isCall= true; } } __log.debug(" isSpringCall: "+isCall); return isCall; }
..................... ............... ... }
LocalThread上下文环境,可以通过继承InheritableThreadLocal类来实现.
/** * 构造可继承线程 * 在创建子线程时,子线程会接收所有可继承的线程局部变量的初始值,以获得父线程所具有的值。 * 应用了“线程局部变量”技术。充当存储或检索一个值时的间接句柄。 * @author * */ class ThreadLocalMap extends InheritableThreadLocal { public final Object childValue(Object parentValue) { // Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。 // 即是说,在多线程应用程序中,不用专门的操作就安全地可以使用Hashtable了;而对于HashMap,则需要额外的同步机制。 Hashtable ht = (Hashtable) parentValue; if (ht != null ) { return ht.clone(); } else { return null ; } }} /** * 工作流API调用时所提供的上下文环境 * @author * */ public class WFAPIContext { final static WFAPIContext wfAPIContext = new WFAPIContext(); static final int HT_SIZE = 7 ; Object tlm; private WFAPIContext() { tlm = new ThreadLocalMap(); } public static void put(String key, Object o) { wfAPIContext.put0(key, o); } public static Object get(String key) { return wfAPIContext.get0(key); } public static void remove(String key) { wfAPIContext.remove0(key); } public static Hashtable getContext() { return wfAPIContext.getContext0(); } private void put0(String key, Object o) { Hashtable ht = (Hashtable) ((ThreadLocalMap) tlm).get(); if (ht == null ) { ht = new Hashtable(HT_SIZE); ((ThreadLocalMap) tlm).set(ht); } ht.put(key, o); } private Object get0(String key) { Hashtable ht = (Hashtable) ((ThreadLocalMap) tlm).get(); if (ht != null && key != null ) { return ht.get(key); } else { return null ; } } private void remove0(String key) { Hashtable ht = (Hashtable) ((ThreadLocalMap) tlm).get(); if (ht != null ) { ht.remove(key); } } private Hashtable getContext0() { return (Hashtable) ((ThreadLocalMap) tlm).get(); }}
