Spring injects Bean into Thread invalid solution

In a Spring project, sometimes a new thread needs to be opened to complete some complex tasks, and some services may need to be injected into the thread. It is a more reasonable way to manage and use services through Spring injection. However, it is invalid to inject the Bean directly in the Thread subclass through annotation.

Because Spring itself defaults that beans are built in singleton mode and are not thread-safe, the injection behavior in Thread subclasses is prohibited, so the bean directly injected in Thread is null, and a null pointer error will occur.

The wrong injection methods and two solutions are listed below.

wrong injection method

@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.
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

报NullpointException。

Injection by encapsulating Thread subclasses

Personally recommend this method, which has less impact on external code.

@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.
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

Call someService normally.

imported from outside

That is, the available instance is obtained first where it can be injected, and it is introduced through the constructor of the Thread subclass. This will affect every code that uses Thread subclasses when modifying the code, and the modification workload will be large.

@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.
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324855449&siteId=291194637