接口逐渐同一格式,相同的代码不断出现,有了优化的需要,就有了接下来的故事
一直想写反射,单奈何例子大同小异,很乏味,先呈上一份不一样的例子。。。
一,框架接口调用重复的方法名称-模板模式
1,重复现象
接口A,B都有个相同的逻辑,根据请求报文组装应答报文后入库,最后发送组装好的应答报文,那就是该租户没有接口权限时,返回下行报文,这些下行报文的父类是相同的;
public calss A extends AbstractFromUp<MsgA>{
@Autowired
private ITableName1Service service;
public void onReceiveErr(MsgContext context){
MsgA msg = context.getMessage();
sendMsgmsgA2(msg);
}
private void sendMsgmsgA2(MsgA msg){
A2 msgA2 = new A2();
//根据请求报文A,组装应答报文A2
//...省略
//入库
service.bizWork(msg ,msgA2);
super.send(msgA2)
}
}
public calss B extends AbstractFromUp<MsgB>{
@Autowired
private ITableName2Service service;
public void onReceiveErr(MsgContext context){
MsgB msg = context.getMessage();
sendMsgmsgB2(msg);
}
private void sendMsgmsgB2(MsgB msg){
B2 msgB2 = new B2();
//根据请求报文B,组装应答报文B2
//...省略
//入库
service.bizWork(msg ,msgB2);
super.send(msgB2)
}
}
2,通过反射优化后
public calss A extends AbstractFromUp<MsgA>{
@Autowired
private ITableName1Service service;
public void onReceiveErr(MsgContext context){
MsgA msg = context.getMessage();
sendMsgDownMsg(msg,"bizWork",service.getClass().getName());
}
}
public calss B extends AbstractFromUp<MsgB>{
@Autowired
private ITableName2Service service;
public void onReceiveErr(MsgContext context){
MsgB msg = context.getMessage();
sendMsgDownMsg(msg,"bizWork",service.getClass().getName());
}
}
//AbstractFromUp 添加方法
public void sendMsgDownMsg(MsgUP msgUP,String methodName,String classPath){
MsgDown msgDown = new MsgDown ();
//根据上行报文组装应答报文
...省略
//入库
//通过反射找到对应的数据库实现类中的方法,保存入库
try{
Class c = Class.forName(classPath);
//看自己工程的bean都放在哪了,没有自己管理的,就从spring里面拿
Object service= c.newInstance();
Class<?> cs = new Class<?>[]{MsgUP.class,MsgDown.class};
//根据方法名和参数列表找到具体方法
Method method1 = c.getMethod(methodName,cs);
//执行方法
method1.invoke(service,msgUP ,msgDown );
}catch(Exception e){
...略
}
super.send(msgDown)
}
二,类设置值
1,类中有重复的set代码
类中有重复大量的字段在set的代码,会显得代码臃肿。
User user = new User();
user.setId(UUID);
...
user.setName(UUID);
User user = new User();
user.setId(UUID);
...
user.setName(UUID);
User user = new User();
user.setId(UUID);
...
user.setName(UUID);
User user = new User();
user.setId(UUID);
...
user.setName(UUID);
2,通过反射优化后
代码量减少,但会引出新的问题,1异常不确定性;2代码阅读没有优化前好
User user = setMethodVal(User.calss,UUID,..."张三");
工具类代码
columns 可以通过配置完成,通过instanceof判定取哪个配置。
private static String spliceSet(String str){
return"set"+str.substring(0,1).toUpperCase()+str.substring(1);
}
private static String [] columns = new String[]{"id","name","age"};
/**
* 按类中顺序设置值
* @param params
* @return
*/
public static <T> T setMethodVal(Class<?> entityClass ,Object... params){
T t = null;
try {
t= (T) entityClass.newInstance();
Method[] methods = t.getClass().getMethods();
for (int i = 0; i < columns.length; i++) {
Object param = params[i];
if (param==null || StringUtils.isBlank(param.toString()))
continue;
lc:
for (int j = 0; j< methods.length ; j++) {
if( methods[j].getName().equals(spliceSet(columns[i]))){
methods[j].invoke(t,param);
break lc;
}
}
}
} catch (IllegalAccessException | InvocationTargetException | InstantiationException e) {
e.printStackTrace();
//log.error("setMethodVal err :[{}]",e.getMessage());
}
return t;
}