使用场景:最近在做一个保费计算的方法,涉及到不同险种的计算,根据三方传来的request请求进行相应的保费计算。最开始用的方法是
switch case
形式,根据对方传来的id逐个判断属于哪种险种,然后就进入相应的方法体。这是一种算是比较low的写法,反正大学那会儿没少用。后来在同事的指导下,换了个高大上的写法。下面就来说说看。。。
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
五种险种,都有一个共同的方法就是计算caculate
,所以就建立了一个公用的接口,再建立5个类来实现这个接口。
接口如下
public interface PremiumCaculator {
DecimalFormat format = new DecimalFormat("##0.00");
Map map = new HashMap();
public Map caculate(String bizInfo) throws Exception;
}
五个实现类就不贴出来了。下面进入正题吧。
这个是我要执行的主类:
//保费计算
@RequestMapping("/baoxianCaculate")
@ResponseBody
public Object baoxianCaculate(HttpServletRequest request) throws IOException,PremiumCaculateException{
String bizInfo = request.getParameter("bizInfo");
String serviceName = "cn.wltc.web.controller.insurance.premium.ZhonganWlzrxQynd";
Class cls = Class.forName(serviceName);
Method m = cls.getDeclaredMethod("caculate",String.class);
Map map = new HashMap();
try {
map = (Map) m.invoke(cls.newInstance(),bizInfo);
map.put("productNo", productNo);
} catch (Exception e) {
String msg = ((InvocationTargetException) e).getTargetException().getMessage();
return new JsonResp(JsonResp.RESULT_FAIL,msg, null);
}
return new JsonResp(JsonResp.RESULT_SUCCESS,null, map);
}
在cn.wltc.web.controller.insurance.premium.ZhonganWlzrxQynd
这个路径下的类中 我需要注入一个service来实现我的功能,但是此时执行时会出现service为空指针的情况。
我的解决方案:
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
Class> cls = wac.getBean("wlLiaPaidAService").getClass();
CargoPaid cPaid = ((BaseService) wac.getBean("cargoPaidService")).findOne(cQuery);
说的通俗一点,由于反射机制使得spring容器失效,没能及时加载进来,这个时候就需要手动从spring中getBean。此时还需要配置一下xml文件:
"cargoPaidService" class="cn.wltc.biz.insurance.service.CargoPaidService">
这样就解决问题了。网上可以查到很多从spring容器中获取bean的方法,可以选择适合的来解决眼前的问题。
还有一个小问题就是,JAVA反射如何捕获自定义的异常?
if (jsonBiz.get("sumInsured")==null) {
throw new PremiumCaculateException("该物流责任险(整车保)无保额信息,请确认信息无误");
}
这个异常是写在实现类里面的,就是java反射需要调用的那个类,自己自定义了一个异常。想要输出异常我的实现方法是:
try {
//要捕获异常的方法
} catch (Exception e) {
String msg = ((InvocationTargetException) e).getTargetException().getMessage();
return new JsonResp(JsonResp.RESULT_FAIL,msg, null);
}
注意这句话((InvocationTargetException) e).getTargetException().getMessage();
反射的地方的代码,还是会对你的自定义异常再一次封装成反射调用失败的异常。 所以如果要得到自己自定义的异常必须要用通过ex.getTargetException()来得到。
参考文献:
Java反射机制详解:http://baike.xsoftlab.net/view/209.html#3_5
spring反射机制:http://www.cnblogs.com/forerver-elf/p/4724199.html
获取Spring容器中的Bean:http://www.bbsmax.com/A/1O5E8aKnJ7/
我也是刚刚入行一年多一点,刚刚接触反射机制,也在学习中,不对的地方可以帮忙点出,或者提出更多的东西一起学习。