前言
体能状态先于精神状态,习惯先于决心,聚焦先于喜好
需求
博主近期处理一个需求,将使用 Spring Quartz 跑批的定时任务改造为对外暴露的接口.
需求分析
这个需求的出发点是这样的,这个系统是一个很古老的系统,使用Spring Quartz,而公司后期已经有专门的定时任务组件了,只要将相应接口暴露出来就行.
由于 Quartz 的定时频率是在代码里写死的,而这个定时任务是用于生成好几家保险公司的对账文件,有时候系统出现问题,生成历史对账文件就变成了一个很棘手的问题,所以很有必要将之改造.
常规开发
常规开发的话,只需要将每个保险公司生成对账文件的方法(因为不同保险公司要求不一样,所以每一家保险公司都需要单独写一个方法)暴露为接口就行了.
比如,有20家保险公司,就暴露20个方法
多想一步:防止系统意外,提供一个集中调用的方法
用上面的小标题,常规开发是可以解决问题的,但是这样一来,一单系统出现了异常,需要手动触发指定日期的对账方法时,就要重复触发n次,所以这里应该提供一个集中触发的方法,在平时,每个保险公司的方法都是单独触发的,在意外情况下则可以单独调用这个总方法,总方法内部自己去调用其他20多个方法.
技术实现
对于20多个方法这里不做赘述,主要是这个总方法怎么写?
常规写法:在总方法中一一罗列调用子方法
将需要被调用的子方法进行罗列,并依次调用
为了防止一个方法出现异常导致后面的任务无法执行,所以每次调用都需要try catch 包围起来
可以想象,这样这个类有多长?
/**
* 总方法调用子方法
*/
public class Demo(){
public boolean allWorkers(){
try{
worker1();
}catch(Exception e){
//todo 错误处理
}
try{
worker2();
}catch(Exception e){
//todo 错误处理
}
try{
worker3();
}catch(Exception e){
//todo 错误处理
}
//其余略...
}
}
多想一步:用反射来解决这个问题
上面的方法虽然可以解决问题,但是使得代码过于冗长,反正这个总方法就是把所有本类中的其他方法调用一下,那么直接使用反射机制获取所有的子方法循环调用即可
回忆反射机制
好记忆不如烂笔头,博主翻了一下之前写的关于反射的系列博文 https://blog.csdn.net/bestcxx/column/info/19241
直接看 (二)利用反射机制实例化类,获取和修改变量,获取和调用方法和构造方法 即可
我们需要参考的demo代码如下
Class<?> obj=Demo4.class;
try {
//获得方法
Method method=obj.getDeclaredMethod("method2", String.class);
//获取一个对象
Object demo4= obj.newInstance();
//允许反射方法调用 private 修饰的方法
method.setAccessible(true);
//反射 调用 方法,并传入参数
method.invoke(demo4, "name2");
实际应用
由于实际项目中使用了 Spring 对 bean 进行管理,所以我们没有必要
Object demo4= obj.newInstance(); 这行代码
但是 method.invoke(demo4, “name2”); 中需要 demo4 是一个对象
在实际操作中,我一共采用了三种操作
- 使用Spring @Autowired 自己注入自己;可行
- 使用 ClassA a=new ClassA(); 可行
- 直接使用this;可行
由于我的方法就是本方法调用本类的其余方法,所以,这里可以使用 this 调用反射方法是最好的方式
@Override
public boolean allWokers(String yyyyMMdd) {
logger.info("调用总方法 allWokers,yyyyMMdd="+yyyyMMdd);
Class<?> demoClass=DemoFacade.class;
//获取所有本类的公共方法
Method[] methods=demoClass.getMethods();
//遍历调用
for(Method m:methods) {
//与本方法同名的方法不调用
if(!m.getName().equals("allWokers")) {
try {
m.invoke(this, yyyyMMdd);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return false;
}