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)。