流程引擎核心程式碼(Spring核心原理)★★★★★
阿新 • • 發佈:2019-01-03
import java.util.HashMap; /** * 每一個流程的全域性上下文(靜態內部類實現的單例) * * @author wb-zf300458 on 2018/1/30. */ public class FlowGlobalContext { private ThreadLocal nodeToShareData; private static class GlobalContextHolder { private static final FlowGlobalContext INSTANCE = new FlowGlobalContext(); } private FlowGlobalContext() { nodeToShareData = new ThreadLocal(); nodeToShareData.set(new HashMap<String,Object>()); } public static final FlowGlobalContext getInstance() { return GlobalContextHolder.INSTANCE; } public ThreadLocal getNodeToShareData(){ return nodeToShareData; } }
----------------------------------------------------------------------------
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.springframework.util.Assert; /** * 單例工廠(單例、單例登錄檔) * * @author wb-zf300458 on 2018/1/31. */ public class AbstractSingleBeanFactory { /** * 充當了Bean例項的快取,實現方式和單例登錄檔相同 */ private final Map singletonCache; private AbstractSingleBeanFactory() { singletonCache = new ConcurrentHashMap(256); } private static class AbstractBeanFactoryHolder { private static final AbstractSingleBeanFactory INSTANCE = new AbstractSingleBeanFactory(); } public static AbstractSingleBeanFactory getInstance() { return AbstractBeanFactoryHolder.INSTANCE; } public Object getBean(String name) throws Exception{ Assert.notNull(name, "'name' must not be null"); Object bean = this.singletonCache.get(name); // A與B執行緒同一時刻執行到該地方 if (bean == null) { //使用了程式碼鎖定同步塊,原理和同步方法相似,但是這種寫法效率更高 // A與B執行緒同一時刻執行到這 synchronized (this.singletonCache) { // A運氣好先執行,B在等待,A處理完畢,會在集合中有name相關的例項,然後B結束等待,進入此程式碼,而此時集合中 // 有A執行緒執行後放入的例項。所以下面需要再次判斷,防止B執行緒多new 一個例項出來。 if (bean == null) { bean = this.singletonCache.get(name); if (bean == null) { bean = Class.forName(name).newInstance(); this.singletonCache.put(name, bean); return bean; } } } } return bean; } }
------------------------------------------------------------------------------
import com.wdk.finance.enums.BizTypeEnum; import com.wdk.finance.node.flow.AbstractProcessFlow; import com.wdk.finance.node.factory.bean.AbstractSingleBeanFactory; /** * 流程工廠 * * @author wb-zf300458 on 2018/1/27. */ public class FlowFactory { /** * * @param bizType * @return */ public AbstractProcessFlow getProcessFlow(String bizType) throws Exception { if (bizType == null) { return null; } if (String.valueOf(4).equals(bizType)) { return (AbstractProcessFlow)AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.flow.PerformanceInvoiceProcessFlow"); } return null; } }
------------------------------------------------------------------------------
import com.wdk.finance.node.AbstractNode;
/**
*
*
* @author wb-zf300458 on 2018/1/26.
*/
public class A extends AbstractNode {
@Override
public void execute() throws Exception {
}
}
------------------------------------------------------------------------------
import com.wdk.finance.node.AbstractNode;
/**
*
*
* @author wb-zf300458 on 2018/1/25.
*/
public class B extends AbstractNode {
@Override
public void execute() throws Exception {
}
}
------------------------------------------------------------------------------
import com.wdk.finance.node.AbstractNode;
import com.wdk.finance.node.context.FlowGlobalContext;
/**
* 流程完畢移除該流程執行緒的引數值
*
* @author wb-zf300458 on 2018/1/30.
*/
public class RemoveThreadLocalValue extends AbstractNode {
@Override
public void execute() throws Exception {
FlowGlobalContext.getInstance().getNodeToShareData().remove();
}
}
------------------------------------------------------------------------------
import java.util.ArrayList;
import java.util.List;
import com.wdk.finance.node.AbstractNode;
/**
* 抽象的處理流程
*
* @author wb-zf300458 on 2018/1/27.
*/
public abstract class AbstractProcessFlow implements Flow {
List<AbstractNode> flowCombinations = new ArrayList<>();
}
------------------------------------------------------------------------------
import java.util.List;
import com.wdk.finance.node.AbstractNode;
/**
* 流程介面
*
* @author wb-zf300458 on 2018/1/27.
*/
public interface Flow {
/**
* 獲取流程組合
*
* @return
*/
public List<AbstractNode> getFlowCombination() throws Exception;
}
------------------------------------------------------------------------------
import java.util.List;
import com.wdk.finance.node.AbstractNode;
import com.wdk.finance.node.factory.bean.AbstractSingleBeanFactory;
/**
* 履約單據處理流程
*
* @author wb-zf300458 on 2018/1/27.
*/
public class PerformanceInvoiceProcessFlow extends AbstractProcessFlow{
@Override
public List<AbstractNode> getFlowCombination() throws Exception {
flowCombinations.add((AbstractNode)AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.flow.biz.A"));
flowCombinations.add((AbstractNode)AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.flow.biz.B"));
flowCombinations.add((AbstractNode)AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.flow.biz.RemoveThreadLocalValue"));
return flowCombinations;
}
}
------------------------------------------------------------------------------
public class MySingleton {
private static class MySingletonHandler {
private static MySingleton instance = new MySingleton();
}
private MySingleton() {}
public static MySingleton getInstance() {
return MySingletonHandler.instance;
}
}
------------------------------------------------------------------------------
import com.wdk.finance.node.NodeHandler;
import com.wdk.finance.node.factory.bean.AbstractSingleBeanFactory;
import com.wdk.finance.node.factory.flow.FlowFactory;
/**
* @author wb-zf300458 on 2018/1/31.
*/
public class NodeTest {
public static void main(String[] args) throws Exception {
FlowFactory flowFactory = (FlowFactory)AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.factory.flow.FlowFactory");
NodeHandler nodeHandler = (NodeHandler)AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.NodeHandler");
try {
nodeHandler.handlerNode(flowFactory.getProcessFlow("4"));
} catch (Exception e) {
e.printStackTrace();
}
}
}
------------------------------------------------------------------------------
import com.wdk.finance.node.factory.bean.AbstractSingleBeanFactory;
/**
* 測試多執行緒環境下,AbstractSingleBeanFactory建立的物件單例,是否正確
*
* @author wb-zf300458 on 2018/2/1.
*/
public class TestAbstractSingleBeanFactory extends Thread {
@Override
public void run() {
try {
while (true){
System.out.println(
AbstractSingleBeanFactory.getInstance().getBean("com.wdk.finance.node.NodeHandler").hashCode());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 測試多執行緒下的
TestAbstractSingleBeanFactory[] mts = new TestAbstractSingleBeanFactory[1000];
for (int i = 0; i < mts.length; i++) {
mts[i] = new TestAbstractSingleBeanFactory();
}
for (int j = 0; j < mts.length; j++) {
mts[j].start();
}
}
}
------------------------------------------------------------------------------
import com.wdk.finance.node.context.FlowGlobalContext;
/**
* 測試多執行緒環境下的靜態內部類實現的單例
*/
public class TestThreadLocal extends Thread{
@Override
public void run() {
FlowGlobalContext.getInstance().getNodeToShareData().set(1);
while (true){
FlowGlobalContext globalContext = FlowGlobalContext.getInstance();
ThreadLocal threadLocal = globalContext.getNodeToShareData();
Integer i = (Integer)threadLocal.get();
System.out.println(Thread.currentThread().getName()+","+i);
if(null != i){
i++;
}
threadLocal.set(i);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
// 測試多執行緒下的
TestThreadLocal[] mts = new TestThreadLocal[5];
for(int i = 0 ; i < mts.length ; i++){
mts[i] = new TestThreadLocal();
}
for (int j = 0; j < mts.length; j++) {
mts[j].start();
}
}
}
------------------------------------------------------------------------------
import java.util.Map;
import com.wdk.finance.node.context.FlowGlobalContext;
/**
* 流程相關的全域性上下文工具類
*
* @author wb-zf300458 on 2018/2/1.
*/
public class FlowGlobalContextUtils {
/**
* 新增值到全域性map裡面
*
* @param key
* @param value
*/
public static void put(String key, Object value) {
((Map<String, Object>)FlowGlobalContext.getInstance().getNodeToShareData().get()).put(key, value);
}
/**
* 從全域性map裡面取值
*
* @param key
*/
public static Object get(String key) {
return ((Map<String, Object>)FlowGlobalContext.getInstance().getNodeToShareData().get()).get(key);
}
}
------------------------------------------------------------------------------
import java.util.Map;
import com.wdk.finance.node.context.FlowGlobalContext;
/**
* 抽象節點(單例模式)
*
* @author wb-zf300458 on 2018/1/25.
*/
public abstract class AbstractNode implements Node {
/**
* 節點共享資料
*/
protected Map<String, Object> nodeToShareData;
/**
* 外部呼叫(模板方法)
* @return
* @throws Exception
*/
protected void invoke() throws Exception {
beforeExecute();
execute();
}
/**
* 執行目標方法之前
*
* @return
* @throws Exception
*/
public void beforeExecute()throws Exception{
// 獲取節點共享的資料
this.nodeToShareData = (Map<String, Object>)FlowGlobalContext.getInstance().getNodeToShareData().get();
}
}
------------------------------------------------------------------------------
/**
* 抽象的節點介面
*
* @author by wb-zf300458 on 2018/1/25.
*/
public interface Node {
/**
* 執行目標方法
*
* @return
* @throws Exception
*/
public void execute() throws Exception;
}
------------------------------------------------------------------------------
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.wdk.finance.node.context.FlowGlobalContext;
import com.wdk.finance.node.flow.AbstractProcessFlow;
/**
* 抽象的節點處理者
*
* @author wb-zf300458 on 2018/1/25.
*/
public class NodeHandler {
public void handlerNode(AbstractProcessFlow abstractProcessFlow) throws Exception{
// 預設都要執行下一個節點
((Map<String, Object>)FlowGlobalContext.getInstance().getNodeToShareData().get()).put("nodeResult", true);
List<AbstractNode> abstractNodes = abstractProcessFlow.getFlowCombination();
try{
Iterator abstractNodesIterator = abstractNodes.iterator();
while (abstractNodesIterator.hasNext()){
AbstractNode abstractNode = (AbstractNode)abstractNodesIterator.next();
abstractNode.invoke();
// 判斷是否要繼續執行下一個節點
if (!((Boolean)abstractNode.nodeToShareData.get("nodeResult"))) {
if(abstractNodes.size()>1){
abstractNodes.get(abstractNodes.size()-1).invoke();
}
break;
}
}
}catch (Exception e){
if(abstractNodes.size()>1){
abstractNodes.get(abstractNodes.size()-1).invoke();
}
throw e;
}
}
}