解决Spring在Thread中注入Bean无效的问题

 更新时间:2022年02月24日 09:41:16   作者:嗡汤圆  
这篇文章主要介绍了解决Spring在Thread中注入Bean无效的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

在Thread中注入Bean无效

在Spring项目中,有时需要新开线程完成一些复杂任务,而线程中可能需要注入一些服务。而通过Spring注入来管理和使用服务是较为合理的方式。但是若直接在Thread子类中通过注解方式注入Bean是无效的。

因为Spring本身默认Bean为单例模式构建,同时是非线程安全的,因此禁止了在Thread子类中的注入行为,因此在Thread中直接注入的bean是null的,会发生空指针错误。

以下分别列举错误的注入方法和两种解决方式。

错误的注入方法

@Controller
public class SomeController{
    @ResponseBody
    @RequestMapping("test")
    String testInjection(){
        // 直接创建并运行线程
        new SomeThread().start();
    }
}
// 直接编写线程
public SomeThread extends Thread {
    @Autowired
    SomeService someService;
    @Override
    public void run(){
        // do something...
        someService.doSomething();
        // 此时 someService实例是null.
    }
}

报NullpointException。

通过封装Thread子类注入

个人比较推荐这种方法,对外部代码的影响较小。

@Controller
public class SomeController{
    // 通过注解注入封装线程的Bean
    @AutoWired
    SomeThread someThread;
    @ResponseBody
    @RequestMapping("test")
    String testInjection(){
        // 通过注入的Bean启动线程
        someThread.execute();
    }
}
@Component
public class SomeThread {
    // 封装Bean中注入服务
    @AutoWired
    SomeService someService
    public void execute() {
        new Worker().start();
    }
    // 线程内部类,Thread或者Runnable均可
    private class Worker extends Thread {
        @Override
        public void run() {
            // do something...
            SomeThread.this.someService.doSomething();
            // 此时someService已被注入,非null.
        }
    }
}

正常调用someService。

通过外部引入

即在可以注入的地方先得到可用的实例,在通过Thread子类的构造函数引入。这样会使得在进行代码修改时,影响到每个使用Thread子类的代码,修改工作量大。

@Controller
public class SomeController{
    // 通过注解注入Service
    @AutoWired
    SomeService someService;
    @ResponseBody
    @RequestMapping("test")
    String testInjection(){
        // 通过构造函数从外部引入
        new Worker(someService).start();
    }
}
public class SomeThread {
    private SomeService someService;
    public SomeThread(SomeService someService){
        // 通过构造函数从外部引入
        this.someService  = someService;
    }
    @Override
    public void run() {
        // do something...
        someService.doSomething();
        // 此时someService非null.
    }
}

Spring多线程中bean的注入问题

最近碰到了一个问题,使用SSM框架,在Service层需要另开一个线程,这个线程专门用来做一些操作,并将结果写入数据库中。但是在线程中使用@Resource或者@Autowired注入全部为NULL,原来是Spring不能在线程中注入。

网上的主要解决方法有

  • 将需要的Bean作为线程的的构造函数的参数传入
  • 使用ApplicationContext.getBean方法来静态的获取Bean

我的线程中所需要的Bean的数量较多,并且以后还有可能增加或者减少,所以方法1并不适合

我的Spring配置文件并不只一个,而且使用getBean方法需要重新加载一遍所有的Bean,这样也违反的Spring的IoC,并不是我想要的,所以也不采用方法2

最后确定使用内部类的方法,将线程中需要的Bean提前注入好,大致的结构如下:

@Service
class TestExample{
    //这两个为线程所需要的Bean
    @Resource
    TestDao testDao;
    @Resource
    NeedDap needDao;
    public void serviceExecute(){
        //在这里开启线程,执行操作
        ThreadExample te = new ThreadExample();
        te.start();
    }
    
    //内部类
    private class ThreadExample extends Thread{
        public ThreadExample(){
            //也可以在构造函数中传入参数
        }
        public void run(){
            //这里为线程的操作
            //就可以使用注入之后Bean了
        }
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 解决JAVA8 Collectors.toMap value为null报错的问题

    解决JAVA8 Collectors.toMap value为null报错的问题

    这篇文章主要介绍了解决JAVA8 Collectors.toMap value为null报错的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • Java实现精准Excel数据排序的方法详解

    Java实现精准Excel数据排序的方法详解

    在数据处理或者数据分析的场景中,需要对已有的数据进行排序,在Excel中可以通过排序功能进行整理数据,而在Java中,则可以借助Excel表格插件对数据进行批量排序,下面我们就来学习一下常见的数据排序方法吧
    2023-10-10
  • 初始JAVA模块化开发的超详细步骤(适合菜鸟)

    初始JAVA模块化开发的超详细步骤(适合菜鸟)

    这篇文章主要介绍了初始JAVA模块化开发的超详细步骤,详细解释了模块描述符的职责、模块路径的概念以及如何使用命令行运行模块化Java程序,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2025-03-03
  • Spring Mybatis Mapper模糊查询的几种方法

    Spring Mybatis Mapper模糊查询的几种方法

    在Spring结合Mybatis进行开发时,实现模糊查询是一个常见需求,在Mybatis中,LIKE查询可以通过多种方式实现,本文给大家介绍了Spring Mybatis Mapper模糊查询的几种方法,需要的朋友可以参考下
    2024-03-03
  • springboot整合xxl-job的示例代码

    springboot整合xxl-job的示例代码

    这篇文章主要介绍了springboot整合xxl-job的示例代码,主要分为三大模块,分别是调度中心、执行器和配置定时任务的过程,本文给大家介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • Maven发布项目 (jar包) 到Nexus私服中的操作

    Maven发布项目 (jar包) 到Nexus私服中的操作

    这篇文章主要介绍了Maven发布项目 (jar包) 到Nexus私服中的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • 基于springboot微信公众号开发(微信自动回复)

    基于springboot微信公众号开发(微信自动回复)

    这篇文章主要介绍了基于springboot微信公众号开发(微信自动回复),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • Mybatis查询时的延迟加载解析

    Mybatis查询时的延迟加载解析

    这篇文章主要介绍了Mybatis查询时的延迟加载解析,先从单表查询,需要时再从关联表去关联查询,能大大提高数据库性能,因为查询单表要比关联查询多张表速度要快,延迟加载分为两种:深度延时加载,侵入式延迟加载,需要的朋友可以参考下
    2023-10-10
  • java实现简易点菜器

    java实现简易点菜器

    这篇文章主要为大家详细介绍了java实现简易点菜器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • 一文带你你搞懂Java的3种IO模型

    一文带你你搞懂Java的3种IO模型

    在Java中,一共有三种IO模型,分别是阻塞IO(BIO)、非阻塞IO(NIO)和异步IO(AIO),本文将给大家详解的介绍这三种IO模型,文中有相关的代码示例,需要的朋友可以参考下
    2023-05-05

最新评论