在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在Thread中注入Bean无效的解决方式的更多相关文章

  1. spring给容器中注入组件的几种方式

    目录 环境搭建 spring给容器中注入组件 1.包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)适用于把自己写的类加入组件(默认ID类名 ...

  2. Spring IOC容器中注入bean

    一.基于schema格式的注入 1.基本的注入方式 (属性注入方式) 根据setXxx()方法进行依赖注入,Spring只会检查是否有setter方法,是否有对应的属性不做要求 <bean id ...

  3. Spring在代码中获取bean的几种方式(转:http://www.dexcoder.com/selfly/article/326)

    方法一:在初始化时保存ApplicationContext对象 方法二:通过Spring提供的utils类获取ApplicationContext对象 方法三:继承自抽象类ApplicationObj ...

  4. Spring为IOC容器注入Bean的五种方式

    一 @Import导入组件,id默认是组件的全类名 //类中组件统一设置.满足当前条件,这个类中配置的所有bean注册才能生效: @Conditional({WindowsCondition.clas ...

  5. Spring在代码中获取bean的几种方式

    方法一:在初始化时保存ApplicationContext对象 方法二:通过Spring提供的utils类获取ApplicationContext对象 方法三:继承自抽象类ApplicationObj ...

  6. Spring在代码中获取bean的几种方式(转)

    获取spring中bean的方式总结: 方法一:在初始化时保存ApplicationContext对象 ApplicationContext ac = new FileSystemXmlApplica ...

  7. spring 在容器中一个bean依赖另一个bean 需要通过ref方式注入进去 通过构造器 或property

    spring  在容器中一个bean依赖另一个bean 需要通过ref方式注入进去 通过构造器 或property

  8. spring 注入bean的两种方式

    我们都知道,使用spring框架时,不用再使用new来实例化对象了,直接可以通过spring容器来注入即可. 而注入bean有两种方式: 一种是通过XML来配置的,分别有属性注入.构造函数注入和工厂方 ...

  9. Spring的DI(Ioc) - 注入bean 和 基本数据类型

    注入bean有两种方式: 注入其他bean: 方式一 <bean id="orderDao" class="cn.itcast.service.OrderDaoBe ...

随机推荐

  1. 重读APUE(13)-可靠信号

    在信号产生和传递之间有一段时间间隔,称为信号是未决的: 进程可以设置阻塞信号传递:如果进程产生了一个阻塞的信号,并且对该信号的动作是系统默认或者捕捉该信号,则该进程保持此信号为未决状态,直到该进程对此 ...

  2. Flutter用dio封装http网络请求,设置统一的请求地址、headers及处理返回内容

    封装http请求是项目中经常需要做的,常用于设置通用请求地址.请求headers以及处理返回结果,例如在项目中开发地址.测试地址.上线地址是不一样的,当在封装的请求设置好默认地址之后只需要改一个地址而 ...

  3. spring配置hibernate在使用oracle驱动时报错Cannot load JDBC driver class 'oracle.jdbc.driver.OracleDriver '

    在看到这个错误的时候就感觉有点不对劲了,在错误的结尾和引号之间还有空间,如果敏锐的点应该察觉到可能是空格问题.由于本人的粗心导致这个问题一直困扰了我接近一个上午. 在排查这个问题的时候首先想到的就是关 ...

  4. APP_DEBUG改成false上线之后发现:“页面错误!请稍后再试~

      TP框架 页面错误!请稍后再试 把APP_DEBUG改成false上线之后发现:"页面错误!请稍后再试-". 问题一般是出在,display() 指定某个具体的模板文件后win ...

  5. linux rtc中废弃的接口和新的接口

    1. 废弃的接口 rtc_tm_to_time 2. 替换废弃接口的新接口 rtc_tm_sub

  6. 《maven实战》笔记(2)----一个简单maven项目的搭建,测试和打包

    参照<maven实战>在本地创建对应的基本项目helloworld,在本地完成后项目结构如下: 可以看到maven项目的骨架:src/main/java(javaz主代码)src/test ...

  7. 【leetcode】507. Perfect Number

    problem 507. Perfect Number solution: /* class Solution { public: bool checkPerfectNumber(int num) { ...

  8. iOS面试-关于性能优化

    目录 我要给出的建议将分为三个不同的等级: 入门级. 中级和进阶级: 入门级(这是些你一定会经常用在你app开发中的建议) 1. 用ARC管理内存2. 在正确的地方使用reuseIdentifier3 ...

  9. swift 第七课 xib 约束的优先级

    前期要实现 一个自适应的label 的时候,就知到xib 约束是有优先级的,一直为深入研究: 乘写这个 博客的机会 ,试验下xib 约束的等级 …… 抱歉要查资料,在重新实践,先把主要浏览的网页 连接 ...

  10. 在win10上使用premake工具和vs2017编译运行Box2D源码和Testbed

    1.从github上下载Box2D源码的zip包 2.解压缩zip包 3.从premake网站下载premake5工具,解压后得到premake5.exe 4.将premake5.exe拷贝到Box2 ...