1, 前面一篇的文章介紹了TransactionTemplate的基本使用方法.
同事在其基礎上又做了一層封裝,這樣更貼合本公司的業務與規范.
2, 首先定義了兩個接口:
ServiceTemplate ----> 對TransactionTemplate進行了封裝
1 public interface ServiceTemplate { 2 3 /** 4 * <pre> 無事務模板執行業務處理 5 * 1. 異常捕獲,及分類處理 6 * 2. 業務日志記錄 7 * </pre> 8 * 9 * @param <T> 10 * @param clazz 返回對象 11 * @param action 業務操作回調的接口 12 * @return 服務返回對象 13 */ 14 <T> T executeWithoutTransaction(Class<? extends Result> clazz, ServiceCallback action); 15 16 /** 17 * <pre> 支持本地事務模板執行業務處理 18 * 1. 本地事務封裝 19 * 2. 異常捕獲,及分類處理 20 * 3. 業務日志記錄 21 * </pre> 22 * 23 * @param <T> 24 * @param clazz 返回對象 25 * @param action 業務操作回調的接口 26 * @return 服務返回對象 27 */ 28 <T> T execute(Class<? extends Result> clazz, ServiceCallback action); 29 30 }
ServiceCallback ----> 對TransactionCallBack進行了封裝
1 public interface ServiceCallback { 2 /** 3 * <pre> 校驗 4 * 對於校驗不通過,異常驅動返回 5 * </pre> 6 */ 7 void doLock(); 8 9 /** 10 * <pre> 校驗 11 * 對於校驗不通過,異常驅動返回 12 * </pre> 13 */ 14 void check(); 15 16 /** 17 * <pre> 執行業務邏輯 18 * </pre> 19 * @return 20 */ 21 Result executeService(); 22 }
ServiceTemplate的具體實現如下:
1 public class ServiceTemplateImpl implements ServiceTemplate { 2 3 /** 事務模板 */ 4 @Autowired 5 private TransactionTemplate transactionTemplate; 6 7 @Override 8 public <T> T executeWithoutTransaction(Class<? extends Result> clazz, 9 ServiceCallback action) { 10 Result result = null; 11 try { 12 // 執行校驗 13 action.check(); 14 //鎖操作 15 action.doLock(); 16 17 // 執行處理邏輯 18 result = action.executeService(); 19 //可以對結果進行初步校驗TODO 20 21 22 } catch (自定義異常 e) { 23 //打日志TODO 24 return (T) result; 25 26 } catch (Throwable e2) { 27 //打日志TODO 28 return (T) result; 29 } 30 31 return (T) result; 32 } 33 34 @Override 35 @SuppressWarnings("unchecked") 36 public <T> T execute(final Class<? extends Result> clazz, final ServiceCallback action) { 37 T acResult = (T) transactionTemplate.execute(new TransactionCallback() { 38 /** 39 * @see org.springframework.transaction.support.TransactionCallback#doInTransaction(org.springframework.transaction.TransactionStatus) 40 */ 41 public Object doInTransaction(TransactionStatus status) { 42 43 Result result = null; 44 45 try { 46 47 result = clazz.newInstance(); 48 // 執行校驗邏輯 49 action.check(); 50 51 //鎖操作 52 action.doLock(); 53 54 // 執行處理邏輯 55 result = action.executeService(); 56 // 返回值異常處理 57 if (result == null || !(result instanceof BaseResult)) { 58 throw new 自定義異常; 59 } 60 61 } catch (自定義異常 e) { 62 // 業務異常捕獲, 回滾, 打日志TODO 63 64 status.setRollbackOnly(); 65 66 return result; 67 } catch (Throwable e2) { 68 // 系統異常捕獲, 回滾, 打日志TODO 69 status.setRollbackOnly(); 70 return result; 71 } 72 return result; 73 } 74 }); 75 return acResult; 76 } 77 78 }
3, 在業務方法中使用ServiceTemplate, 通過構建ServiceCallBack匿名內部類的方式, 傳遞具體的業務代碼:
1 public Result update(final BaseOrder baseOrder) { 2 return serviceTemplate.execute(BooleanResult.class, new ServiceCallback() { 3 @Override 4 public void doLock() { 5 //進行鎖操作 6 } 7 8 @Override 9 public void check() { 10 //進行校驗 11 } 12 13 @Override 14 public Result executeService() { 15 Result result = new Result(); 16 //具體的業務代碼 17 return result; 18 } 19 }); 20 }
注意: 如果是不需要加事務的方法, 如查詢 ,那么調用serviceTemplate的executeWithoutTransaction即可