通過反射獲得並調用類的方法導致@Autowired注入失效的解決方案

引言

最近在優化公司平臺項目,由於該平臺是to B性質,所以有些需求需要 定製化開發,爲了使代碼向上兼容並且更加的靈活,所以用到了反射,但是在使用過程中遇到了@Autowired失效問題。

問題解析:

其實出現這個問題的原因很簡單,就是我們通過獲得的類沒有納入spring容器管理,下面來看一下錯誤代碼:

反射代碼如下: 

                 //爲了測試寫死了
                String className ="TaiLongM1CallBackService";
                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 ="TaiLongM1CallBackService";
                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.zqf.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);
 
    }
}

小結

至此,就解決了這個問題,遇到問題我們首先要分析一下出現問題的原因,然後對症下藥,就可以快速解決了

 

發佈了364 篇原創文章 · 獲贊 389 · 訪問量 141萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章