Spring项目bean 无法注入问题--Thread中注入Bean无效

古城微笑少年丶 2022-04-16 01:51 919阅读 0赞

有时候在spring项目中可能会遇到依赖的属性没有被注入,这个时候可能有很多原因。spring默认是单例的,通常注入的时候我们使用比较多的是@Autowired,这个注解默认按照类型注入(同时会处理依赖关系)。

当没有注入的时候,即使用的时候值为null ,会报空指针异常 ,需要查看此属性的bean 有没有被spring初始化并管理,比如bean有没有被扫描到,或者配置。

今天这这里我研究的是另一种情况,Thread中注入Bean

在Spring项目中,有时需要新开线程完成一些复杂任务,而线程中可能需要注入一些服务(例如此新开的线程需要将得到的数据写入数据库等)。而通过Spring注入来管理和使用服务是较为合理的方式。但是若直接在Thread子类中通过注解方式注入Bean是无效的。@Resource或者@Autowired注入全部为NULL,

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

错误代码X———这里的ywBuildingService 是不能被注入的

  1. @Service
  2. public class GuanLinSyncQueue implements Runnable {
  3. private Logger logger = Logger.getLogger(GuanLinSyncQueue.class);
  4. private static final String qianchuanCommunityCode = Global.getConfig("qianchuanCommunityCode");
  5. @Autowired
  6. private YwBuildingService ywBuildingService;
  7. @PostConstruct
  8. public void init() {
  9. Thread thread = new Thread(new GuanLinSyncQueue());
  10. thread.start();
  11. }
  12. @Override
  13. public void run() {
  14. ywBuildingService.save(ywBuildingPojo)
  15. }
  16. }

对于此有如下两种解决方法:

  1. 将需要的Bean作为线程的的构造函数的参数传入
  2. 将线程类作为服务类的内部类,Thread或者Runnable均可

方案1:

对于第一种方法,需要将要用到的bean 全部当作线程类的属性,如果bean数量少,也比较方便。注意这个线程类中引入了 ywBuildingService 这个属性。并且在GuanLinSyncQueue 这个可以被spring 管理的bean中注入 ywBuildingService 并通过构造函数 将ywBuildingService 传给了MyThread

  1. public class MyThread implements Runnable {
  2. private Logger logger = Logger.getLogger(GuanLinSyncQueue.class);
  3. private static final String qianchuanCommunityCode = Global.getConfig("qianchuanCommunityCode");
  4. private YwBuildingService ywBuildingService;
  5. //构造方法 传入spring 容易 中的 ywBuildingService
  6. public MyThread(YwBuildingService ywBuildingService) {
  7. super();
  8. this.ywBuildingService = ywBuildingService;
  9. }
  10. @Override
  11. public void run() {
  12. ywBuildingService.save(ywBuildingPojo)
  13. }
  14. }
  15. ------------------------------------------分割线--------------------------------
  16. @Service
  17. public class GuanLinSyncQueue{
  18. private Logger logger = Logger.getLogger(GuanLinSyncQueue.class);
  19. private static final String qianchuanCommunityCode = Global.getConfig("qianchuanCommunityCode");
  20. @Autowired
  21. private YwBuildingService ywBuildingService;
  22. @PostConstruct
  23. public void init() {
  24. Thread thread = new Thread(new MyThread(ywBuildingService));
  25. thread.start();
  26. }
  27. }

方案2:推荐方案!!!将线程类作为服务类的内部类,可以方便直接使用外部类中注入的bean.

  1. @Service
  2. public class GuanLinSyncQueue{
  3. private Logger logger = Logger.getLogger(GuanLinSyncQueue.class);
  4. private static final String qianchuanCommunityCode = Global.getConfig("qianchuanCommunityCode");
  5. @Autowired
  6. private YwBuildingService ywBuildingService;
  7. @PostConstruct
  8. public void init() {
  9. new worker().start();
  10. }
  11. private class worker extends Thread{
  12. @Override
  13. public void run() {
  14. //做自己想做的事情
  15. ywBuildingService.save(ywBuildingPojo);
  16. }
  17. }
  18. }

发表评论

表情:
评论列表 (有 0 条评论,919人围观)

还没有评论,来说两句吧...

相关阅读