目录
问题
原因
解决方案
这是我在开发语音指令识别功能时遇到的问题,在将语音转成文字后需要进行指令匹配,指令匹配成功,就会获得对应的处理方法名称以及所属类,然后通过反射机制去执行该方法完成指令对应的操作
部分代码如下:
@Component public class MethodSet { private final Map> methodMap = new HashMap<>(); public Map > getMethodMap() { methodMap.put("countOrder", OrderCommand.class); methodMap.put("takeOrder",OrderCommand.class); //。。。。其他命令与对应的类 return methodMap; } }
log.info("method key:{}",reply); Class> aClass = methodSet.getMethodMap().get(reply); Method method = aClass.getMethod(reply); Object result = method.invoke(aClass.getDeclaredConstructor().newInstance()); reply = (String) result;
在获取到需要通过反射执行的方法,以及方法所属类之后就能进行调用指令方法了,但是我的指令类内部依赖了相关Service类(被spring容器管理)代码如下:
@Component public class OrderCommand{ @Autowired private StoreOrderService storeOrderService; public String countOrder(){ System.out.println("订单统计方法执行"); MaporderNumbers = storeOrderService.getOrderNumbers(); //其他逻辑。。。。。 }; //。。。。。。。 }
此时就抛出了空指针异常,提示我storeOrderService.getOrderNumbers()方法并不存在,也就是依赖并没有注入成功。
在我搜寻资料后也是找到了原因,就是被反射的类无法被spring管理
参考博客文章:@Autowired被反射调用时,空指针错误_mock@autowired对象空指针-CSDN博客
手动去完成@Autowired效果,交给spring容器管理。
步骤:
通过spring上下文ApplicationContext的getBean(Class
)方法按照类型获取bean实例 通过ApplicationContext的getAutowireCapableBeanFactory()方法获取到AutowireCapableBeanFactory对象使用它的autowireBean(obj)方法来手动处理Bean的自动装配。
修改后反射调用代码如下:
Class> aClass = methodSet.getMethodMap().get(reply); Object obj = applicationContext.getBean(aClass); applicationContext.getAutowireCapableBeanFactory().autowireBean(obj); Method method = obj.getClass().getMethod(reply); Object result = method.invoke(obj); reply = (String) result;