通过反射获得并调用类的方法导致@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);
    }
}


小结


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

目录
相关文章
|
4月前
|
C++
c++将一个类的回调函数注入到另一个类中的方法
c++将一个类的回调函数注入到另一个类中的方法
|
10月前
|
Java 容器
Java实现Autowired自动注入
Test2正常 Test3空指针 因为不在容器里
88 0
|
5月前
|
容器
多线程时Autowired自动注入问题
多线程时Autowired自动注入问题
73 2
注解与反射6得到Class类的几种方式
注解与反射6得到Class类的几种方式
|
安全 Java
注解和反射12.动态创建对象执行方法
注解和反射12.动态创建对象执行方法
|
Java 自动驾驶 小程序
java面试题:哪种依赖注入方式你建议使用,构造器注入,还是Setter方法 注入?
java面试题:哪种依赖注入方式你建议使用,构造器注入,还是Setter方法 注入?
java面试题:哪种依赖注入方式你建议使用,构造器注入,还是Setter方法 注入?
|
Java Spring
构造方法注入和设值注入有什么区别?
构造方法注入和设值注入有什么区别?
构造方法注入和设值注入有什么区别?
|
XML Java 数据格式
反射机制(什么是反射、反射操作构造器、方法、字段、反射加载资源)
反射机制(什么是反射、反射操作构造器、方法、字段、反射加载资源)
119 0
反射机制(什么是反射、反射操作构造器、方法、字段、反射加载资源)
【Groovy】MOP 元对象协议与元编程 ( 方法注入 | 使用 @Category 注解进行方法注入 | 分类注入方法查找优先级 )
【Groovy】MOP 元对象协议与元编程 ( 方法注入 | 使用 @Category 注解进行方法注入 | 分类注入方法查找优先级 )
142 0
【Groovy】MOP 元对象协议与元编程 ( 方法注入 | 使用 @Category 注解进行方法注入 | 分类注入方法查找优先级 )