通过反射获得并调用类的方法导致@Autowired注入失效的解决方案

简介: 通过反射获得并调用类的方法导致@Autowired注入失效的解决方案

引言


最近在优化公司平台项目,由于该平台是to B性质,所以有些需求需要 定制化开发,为了使代码向上兼容并且更加的灵活,所以用到了反射,但是在使用过程中遇到了@Autowired失效问题。


问题解析:


其实出现这个问题的原因很简单,就是我们通过获得的类没有纳入spring容器管理,下面来看一下错误代码:


反射代码如下:  


                 //为了测试写死了
                String className ="M1CallBackService";
                Class c = Class.forName(packagePath + className);
                Method m = c.getMethod("callBack", new Class[]{Integer.class});
                //设置参数
                Object[] arguments = new Object[]{new Integer(robotServiceInfo.getRobotId())};
                m.invoke(c.newInstance(), arguments);

通过反射获得类的方法部分代码:

 @Autowired
    private NativeSqlMapper nativeSqlMapper;
    @Autowired
    private EmailService emailService;
    /**
     * @Description: 
     * @author: zhenghao
     * @date: 2019/12/13 14:56
     */
    public void callBack(Integer robotId) {
        String dateStr = DateUtils.getToDayYYYYMMDD();
        List<ExcelSheetModel> excelSheetModelList = new ArrayList<>();
        //信用卡数据回传
        List<Map<String, Object>> callbackDaily = this.getDailyCallbackData(robotId);
        if (callbackDaily == null || callbackDaily.isEmpty()) {
            log.info("今日没有可回传的数据...");
        } else {
。。。。。。。。


当我们运行上面代码的时候,可以正常获得类中的 callBack方法,但是当我们debug的进入该方法的时候会发现,我们通过@Autowired注入的类都是空。


看我们反射中的代码会发现,我们获得类的方式是 class.newInstance 这中写法就没有Spring容器关联起来获取bean,虽然也能拿到但是如果类里面有@Autowired这种方式注入的对象就会空了。


解决方案:


知道错误原因了,解决就比较简单了,我们不要通过class.newInstance方式获取,而是手动通过spring上下文进行获取就可以解决这个问题了,修改后的反射代码

 String className ="M1CallBackService";
                Class c = Class.forName(packagePath + className);
                Object obj = ApplicationContextHelper.popBean(c);
                Method m = c.getMethod("callBack", new Class[]{Integer.class});
                //设置参数
                Object[] arguments = new Object[]{new Integer(robotServiceInfo.getRobotId())};
                m.invoke(obj, arguments);


增加了手动通过spring上下文获得类的代码:


工具类代码如下:

package com.jack.common.utils.service;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
 * @Description: 获得bean
 * @author: zhenghao
 * @date: 2019/12/14 12:04
*/
@Service
public  class ApplicationContextHelper implements ApplicationContextAware {
    private static ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        applicationContext = context;
    }
    /**
     * 获取bean
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T> T popBean(Class<T> clazz) {
        //先判断是否为空
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(clazz);
    }
    public static <T> T popBean(String name, Class<T> clazz) {
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(name, clazz);
    }
}


小结


至此,就解决了这个问题,遇到问题我们首先要分析一下出现问题的原因,然后对症下药,就可以快速解决了

目录
相关文章
|
测试技术
IDEA创建单元测试与测试覆盖率统计
IDEA(IntelliJ IDEA)不仅支持快速基于当前类创建单元测试,还支持代码测试覆盖率的统计,以及生成报告和标记测试运行命中的代码。
3453 0
IDEA创建单元测试与测试覆盖率统计
|
存储 easyexcel Java
EasyExcel教程
EasyExcel教程
16478 0
|
Java 物联网 Maven
Spring Boot 如何集成 MQTT,实现基于 MQTT 协议的消息传递?
Spring Boot 如何集成 MQTT,实现基于 MQTT 协议的消息传递?
3856 2
Spring Boot 如何集成 MQTT,实现基于 MQTT 协议的消息传递?
|
XML 缓存 前端开发
Thymeleaf一篇就够了
Thymeleaf是Springboot官方支持的模板引擎,有着动静分离等独有特点,通过本文简单学习下吧!
62218 24
Thymeleaf一篇就够了
|
监控 Java 关系型数据库
『Jmeter超级干货』| Linux下Jmeter安装配置、脚本设计执行、监控及报告完整过程
『Jmeter超级干货』| Linux下Jmeter安装配置、脚本设计执行、监控及报告完整过程
3213 1
|
SQL 关系型数据库 MySQL
在 MySQL 中使用 `REPLACE` 函数
【8月更文挑战第8天】
1485 7
在 MySQL 中使用 `REPLACE` 函数
|
存储 Java
|
10月前
|
SQL Java 数据库连接
MyBatis-Plus快速入门:从安装到第一个Demo
本文将带你从零开始,快速入门 MyBatis-Plus。我们将首先介绍如何安装和配置 MyBatis-Plus,然后通过一个简单的示例演示如何使用它进行数据操作。无论你是 MyBatis 的新手还是希望提升开发效率的老手,本文都将为你提供清晰的指导和实用的技巧。
2701 0
MyBatis-Plus快速入门:从安装到第一个Demo
|
JavaScript Java API
Java日志通关(二) - Slf4j+Logback 整合及排包
作者日常在与其他同学合作时,经常发现不合理的日志配置以及五花八门的日志记录方式,后续作者打算在团队内做一次Java日志的分享,本文是整理出的系列文章第二篇。
|
存储 SQL NoSQL
mybatis-plus小技能: 分表策略(按年分表和按月分表)
业务场景: 日志、交易流水表或者其他数据量大的表,通过日期进行了水平分表,需要通过日期参数,动态的查询数据。 实现思路:利用MybatisPlus的动态表名插件DynamicTableNameInnerInterceptor ,实现Sql执行时,动态的修改表名。
8465 3
mybatis-plus小技能: 分表策略(按年分表和按月分表)