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

目录
  • 在Thread中注入Bean无效
    • 错误的注入方法
    • 通过封装Thread子类注入
    • 通过外部引入
  • Spring多线程中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了
        }
    }
}

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

(0)

相关推荐

  • 详解SpringBoot 多线程处理任务 无法@Autowired注入bean问题解决

    在多线程处理问题时,无法通过@Autowired注入bean,报空指针异常, 在线程中为了线程安全,是防注入的,如果要用到这个类,只能从bean工厂里拿个实例. 解决方法如下: 1.创建一个工具类代码: package com.hqgd.pms.common; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.spri

  • 解决SpringBoot2多线程无法注入的问题

    1.情况描述 使用springboot2多线程,线程类无法实现自动注入需要的bean,解决思路,通过工具类获取需要的bean 如下 package com.ps.uzkefu.apps.ctilink.handler; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.ps.uzkefu.apps.callcenter.entity.CallRecord; import com.ps.uzkefu.apps.call

  • Spring 多线程下注入bean问题详解

    本文介绍了Spring 多线程下注入bean问题详解,分享给大家,具体如下: 问题 Spring中多线程注入userThreadService注不进去,显示userThreadService为null异常 代码如下: public class UserThreadTask implements Runnable { @Autowired private UserThreadService userThreadService; @Override public void run() { AdeUs

  • Spring如何解决单例bean线程不安全的问题

    首先我们应该知道线程安全问题一般发生在成员变量上,这是为什么啦? 因为成员变量是存放在堆内存中,而堆内存又是线程共享的,这就造成了线程安全问题 因为Spring中的Bean默认是单例的,所以在定义成员变量时也有可能会发生线程安全问题.下面我们就来研究下如何解决Spring中单例Bean的线程安全问题 @RestController //@Scope("prototype") public class BeanController { private int content=0; //基

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

    目录 在Thread中注入Bean无效 错误的注入方法 通过封装Thread子类注入 通过外部引入 Spring多线程中bean的注入问题 网上的主要解决方法有 在Thread中注入Bean无效 在Spring项目中,有时需要新开线程完成一些复杂任务,而线程中可能需要注入一些服务.而通过Spring注入来管理和使用服务是较为合理的方式.但是若直接在Thread子类中通过注解方式注入Bean是无效的. 因为Spring本身默认Bean为单例模式构建,同时是非线程安全的,因此禁止了在Thread子类

  • Spring拦截器中注入Bean失败解放方案详解

    目录 简介 问题重现 解决方案 简介 说明 本文用示例介绍如何解决拦截器中注入Bean失败的问题. 场景 Token拦截器中需要用@Autowired注入JavaJwtUtil类,结果发现注入的JavaJwtUtil为Null. 原因 拦截器的配置类是以new JwtInterceptor的方式使用的,那么这个JwtInterceptor不受Spring管理.因此,里边@Autowired注入JavaJwtUtil是不会注入进去的. 问题重现 代码 application.yml server:

  • 解决Spring Boot 多模块注入访问不到jar包中的Bean问题

    情景描述 一个聚合项目spring-security-tutorial,其中包括4个module,pom如下所示: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://mav

  • 在spring中实例化bean无效的问题

    目录 spring中实例化bean无效 Action中代码如下 applicationContext.xml中配置如下 spring实例化bean顺序问题,导致注入失败 问题如下 原因 解决 spring中实例化bean无效 在做Struts2和Spring整合时遇到Spring实例化无效的情况, Action中代码如下 public class UserAction extends ActionSupport {     @Resource     private UserService us

  • 在zuulFilter中注入bean失败的解决方案

    zuulFilter注入bean失败 一.为什么要用到这个 上周想实现在网关层 zuul 实现用户认证操作,即需要在网关过滤器中调用其他的微服务,按常规做法在 filter 中用 @Autowired 注解一个feign 接口,启动 一直失败,用度娘谷歌查了又查,只找到一些类似[在过滤器中注入bean]失败,但说的都是springMVC 并不是springcloud中的网关层 二.解决方法 查了很久,最终发现问题所在,其实在启动报错就提示很明显了,找不到相关实例,没错feign接口的实现类事实上

  • Spring在代码中获取bean的方法小结

    一.通过Spring提供的ContextLoader WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext(); wac.getBean(beanID); 这种方式不依赖于servlet,不需要注入的方式.但是需要注意一点,在服务器启动时,Spring容器初始化时,不能通过这种方法获取Spring容器 二.实现接口ApplicationContextAware 定义工具类 public class Sp

  • Spring为IOC容器注入Bean的五种方式详解

    这篇文章主要介绍了Spring为IOC容器注入Bean的五种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.class}) @Configuration @Import({Color.class,Red.class,MyImportSelector

  • Spring运行时手动注入bean的方法实例

    有时候,会有这样一个需求,在程序运行时动态生成的对象,需要注入到Spring容器中进行管理. 下面是获取Bean以及注入Bean的工具类 import org.springframework.beans.BeansException; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinit

  • 详解Spring简单容器中的Bean基本加载过程

    本篇将对定义在 XMl 文件中的 bean,从静态的的定义到变成可以使用的对象的过程,即 bean 的加载和获取的过程进行一个整体的了解,不去深究,点到为止,只求对 Spring IOC 的实现过程有一个整体的感知,具体实现细节留到后面用针对性的篇章进行讲解. 首先我们来引入一个 Spring 入门使用示例,假设我们现在定义了一个类 org.zhenchao.framework.MyBean ,我们希望利用 Spring 来管理类对象,这里我们利用 Spring 经典的 XMl 配置文件形式进行

  • Spring在代码中获取bean的几种方式详解

    方法如下 方法一:通过读取XML文件反射生成对象 方法二:通过Spring提供的utils类获取ApplicationContext对象 方法三:继承自抽象类ApplicationObjectSupport 方法四:继承自抽象类WebApplicationObjectSupport 方法五:实现接口ApplicationContextAware 方法六:通过Spring提供的ContextLoader 获取spring中bean的方式总结: 方法一:通过读取XML文件反射生成对象 Applica

随机推荐