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


小结


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

目录
相关文章
|
Java 微服务 Spring
@EnableDiscoveryClient注解的作用
@EnableDiscoveryClient注解的作用 @EnableDiscoveryClient 及@EnableEurekaClient 类似,都是将一个微服务注册到Eureka Server(或其他 服务发现组件,例如Zookeeper、Consul等)
1602 0
|
3月前
|
存储 Java 数据库连接
@OneToOne注解的作用
@OneToOne注解的作用
|
5月前
|
Java API 开发者
Jdk动态代理为啥不能代理Class?
该文章主要介绍了JDK动态代理的原理以及为何JDK动态代理不能代理Class。
Jdk动态代理为啥不能代理Class?
|
6月前
|
Java Spring
@GrpcServise 注解的作用和使用
@GrpcServise 注解的作用和使用
64 0
|
6月前
|
缓存 Java 应用服务中间件
Java编程问题之重试机制问题之在CGLIB中设置目标对象类并创建代理类如何解决
Java编程问题之重试机制问题之在CGLIB中设置目标对象类并创建代理类如何解决
|
7月前
|
Java
java反射-获取类的Class对象方式
java反射-获取类的Class对象方式
|
Java 容器
Java实现Autowired自动注入
Test2正常 Test3空指针 因为不在容器里
136 0
|
8月前
|
容器
多线程时Autowired自动注入问题
多线程时Autowired自动注入问题
226 2
|
8月前
|
C++
c++将一个类的回调函数注入到另一个类中的方法
c++将一个类的回调函数注入到另一个类中的方法
|
NoSQL 安全 Java
踩坑篇之WebSocket实现类中无法使用@Autowired注入对象
踩坑篇之WebSocket实现类中无法使用@Autowired注入对象
227 0