1,問題描述:
日前項目同事遇到一個小問題,來找我討論。他突然要寫一個工具類,專門解決數據庫的統計和字段監控問題。它不在原來體系中,還需要加載各種實體對象,對數據進行統計。
public class MPOperationUtil{
/**
**根據輸入次數,數據庫統計數據數值增加1,5以內,返回錯誤標識XXXX,超過返回錯誤標YYYY。
**/
public static String increaseErrorCode(...){
//庫表Cust的實體對象:最新更新時間的一條客戶信息
CustInfoRepostiory cus
CustInfo cust = cus.findMaxUpdTime(custInfo);
//cus.findMaxUpdTime(custInfo) 出異常NullPointExcepiton
.......
//操作數據庫
cus.update(cust);
return errorCode;
}
public static void resetErrorCode(String errorCode){
CustInfo custInfo;
custInfo.setErrorCode(errorCode);
custInfo.update(custInfo);//毫無疑問,也是報錯。
}
}
先是想看項目中是否有類似的解決方案,沒有。他自己也是試了幾個做法,可是拿不到值。
最後我給了一個解決思路(外部傳值),簡單明瞭的解決。
2,問題分析和解決
- 解決小思路一:spring注入
框架原有的注入
public abstract class BaseAction
/**
*通過指定類型從IOC容器中查找bean
/
protected <T> T get(Class<T> beanType){
return applicationContext.getBean(beanType);
}
對方想的是應用原有代碼中類似例子
public static String increaseErrorCode(...){
....
CustInfo cust = get(CustInfoRepostiory.class).findMaxUpdTime(custInfo);
//照樣出異常NullPointExcepiton:工具類並沒有加入bean體系
.......
//
return errorCode;
}
或者
@Autowired
private CustinfoRepostiory c;//拿不到。
修改方案:因爲MPOperationUtil沒有納入管理。那麼在xxx-services.xml或xxx-util.xml中加入MPOperationUtil對象
1,process(業務交易或單元,包含Action,一對多)上層處理裏視情況加入MPOperationUtil
//Action業務原子操作,流程處理。通過operation定義,採用Java反射技術實現方法的定義
2,<action id="mpOperationUtil" calss="com.XXXX.bbip.jpts.utils.MPOperationUtil"/>
3,public class MPOperationUtil extends BaseAction{
CustInfo cust = get(CustInfoRepostiory.class).
findMaxUpdTime(custInfo);//OK
}
次方案功能上是實現了,但是Java的基本設計思想被破壞。此情此景,通過xml配置實現不是好辦法。
- 解決思路二:直接new對象
這個看視乎可以,直接new出可用的具體實體對象。還有其他情況下,可能破壞了工廠模式,阻礙了擴展性。此工具只服務一個Action。
//直接通過接口,new具體的實體對象
CustInfoRepostiory custInfoRepostiory =(CustInfoRepostiory)new CustInfo();
CustInfo cust = custInfoRepostiory.findMaxUpdTime(custInfo);
//可以
.......
custInfoRepostiory.update(cust);
//由於是重新創建了一個對象,此對象沒有納入事務管理(相對於單獨行動,裸奔),
//它對數據庫的操作是單獨的,存在隱藏風險。
return errorCode;
- 解決思路三:外部傳參數
把外部實體bean傳入,進行操作。相當於引用的思想。
1,外部需要使用的Action,肯定是拿到Context內容的。
public class XXXAction extends BaseAction{
String errorCode=null;
errorCode = MPOperationUtil.increaseErrorCode(
custInfoEntity,get(CustInfoRepository.class));
//把get(CustInfoRepository.class)當參數傳入工具類的方法中
}
2,public class MPOperationUtil{
public static String increaseErrorCode(
CustInfo custInfoEntity,CustInfoRepository custInfoRepository){
....
cust=custInfoRepository.findMaxUpdTime(CustInfoEntity);
custInfoRepository.update(cust);//少改動,高實現
}
}
這個做法很簡單,也很普遍。有時候編程容易陷入困局,自己都沒發現,別人來點一下就通了 。
最後的總結:在諸多方法中比較。
spring注入:可行,但是會打亂原來的xml配置,尤其是在大項目中,對突然的加代碼或配置,有一定的風險。
發射機制:可行,但是項目中沒有使用,明顯的反射機制去拿bean。
外部傳值:可行,在工具類的方法中,把需要的bean實體傳入進來,構造傳值也是同理。
用New創建:不可行,new一個實體對象是可以拿到實體,但是拿不到對象類的上下文內容(context)。