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

        //信用卡数据回传
        List> 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 
     * @return
     */
    public static  T popBean(Class clazz) {
        //先判断是否为空
        if (applicationContext == null) {
            return null;
        }
        return applicationContext.getBean(clazz);
    }
 
 
    public static  T popBean(String name, Class clazz) {
        if (applicationContext == null) {
            return null;
        }
 
        return applicationContext.getBean(name, clazz);
 
    }
}

小结

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

 

你可能感兴趣的:(@JAVA学习)