@Autowired 注入为null

发布时间 2023-11-17 08:59:48作者: 试着看清楚
  1.  背景

  写一个SpringBoot程序,把从接口传过来的数据放进队列,用线程将数据读进数据库和redis。在启动类创建了一个全局队列,通过实现runable接口的方式写了一个线程A,在线程中用@Autowird 注入 service层的对象调用操作数据库的办法。原本打算在启动类通过 new Thread( new A())起一个线程,调试的时候发现线程A中注入的service为null。

   2. 出现问题

  线程A中注入的service为null,导致数据没有写到数据库和redis。

   3. 出现原因

   经过请教同事,知道了new 出来的实例不会交给Spring容器管理,所以实例里面的 service或者dao注入不进来。

   4. 解决办法

  自己写了一个工具类BeanUtils实现不通过new 也能拿到实例,在启动类通过工具管理类getBean拿到实例 起一个线程,解决啦!!!

   5.代码

BeanUtils 工具类的代码如下:
package com.ws.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class BeanUtils implements ApplicationContextAware  {
    protected static ApplicationContext applicationContext ;

    @Override
    public void setApplicationContext(ApplicationContext arg0) throws BeansException {
        if (applicationContext == null) {
            applicationContext = arg0;
        }

    }
    public static Object getBean(String name) {
        //name表示其他要注入的注解name名
        return applicationContext.getBean(name);
    }

    /**
     * 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象
     */
    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

  启动类:

Intersms_userThread intersms_userthread = BeanUtils.getBean(Intersms_userThread.class);

// 通过BeanUtils.getBean的方式拿到intersms_userthread的实例,这样就可以在intersms_userthread中使用@Autowired 注入service了
Thread IntersmsSaveThread = new Thread(intersms_userthread);
IntersmsSaveThread.start();

   6. 待解决

  通过上述步骤,@Autowired 注入为null的问题就解决了,下面是我在实践中遇到的问题,后期不断学习回来继续补充:

  我尝试在Intersms_userThread.java 这个类里面通过

IntersmsService service = BeanUtils.getBean(IntersmsService .class);

  引入service,但是在getBean里面applicationContext为null