Springboot中使用多线程,无法注入Service以及Jpa接口服务

在项目中遇到了一个问题,如题,如图。在运行的时候,使用@Autowired注入的服务均为null,也就是无法注入。

查找资料之后总结,个人觉得有两方面原因,也可以说两方面的解决手段

  1. new出来的线程,不在springboot的容器中,没办法自动注入(具体原理还不是特别懂,需要深入研究,也希望有大佬解答一下),需要手动注入
  2. 修改线程的编写方式,以Springboot的方式来新建一个线程。

先来讲第一种

参考:https://blog.csdn.net/u011493599/article/details/78522315

需要新建一个类实现ApplicationContextAware接口,接口中重写setApplicationContext方法。然后在线程的构造方法中手动注入被@service标记的类。

实现ApplicationContextAware接口的类(类名随意):


 
 
  1. @Component
  2. public class SpringBeanUtil implements ApplicationContextAware{
  3. private static ApplicationContext applicationContext = null;
  4. @Override
  5. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6. SpringBeanUtil.applicationContext = applicationContext;
  7. }
  8. public static Object getBeanByName(String beanName) {
  9. if (applicationContext == null){
  10. return null;
  11. }
  12. return applicationContext.getBean(beanName);
  13. }
  14. public static <T> T getBean(Class<T> type) {
  15. return applicationContext.getBean(type);
  16. }
  17. }

然后就是在编写线程代码的时候,在构造方法中获取要获取的服务


 
 
  1. @Service
  2. @Component
  3. public class DetectionThread extends Thread {
  4. private PictureRespository pictureRespository;
  5. private DetectionService detectionService;
  6. private RetangleRespository retangleRespository;
  7. public DetectionThread(){
  8. this.pictureRespository = SpringBeanUtil.getBean(PictureRespository.class);
  9. System.out.println( 11);
  10. }
  11. public void run(){
  12. }
  13. }

关于第二种,如何更好的将线程加入到Springboot容器中,也就是利用框架的方式开一个线程,待更新

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程环境下,JPA的懒加载会出现No Session错误,原因是每个线程都有自己的session,而懒加载是在session进行的,当线程切换时,session也会切换,导致当前线程没有session而无法进行懒加载操作。 解决方案就是在每个线程手动维护session,可以使用ThreadLocal来存储当前线程的session对象,保证每个线程都有自己的session,并且在使用完后及时关闭session。 以下是一个简单的示例代码,使用SpringBootJPA,其使用了ThreadLocal来存储session对象: ``` @Service public class UserService { @Autowired private UserRepository userRepository; private static final ThreadLocal<Session> sessionThreadLocal = new ThreadLocal<>(); public void doSomethingInNewThread() { new Thread(() -> { Session session = getSession(); User user = userRepository.findById(1L).orElse(null); if (user != null) { // 使用session进行懒加载操作 Hibernate.initialize(user.getOrders()); } closeSession(); }).start(); } private void closeSession() { Session session = sessionThreadLocal.get(); if (session != null) { session.close(); sessionThreadLocal.remove(); } } private Session getSession() { Session session = sessionThreadLocal.get(); if (session == null) { session = entityManager.unwrap(Session.class); sessionThreadLocal.set(session); } return session; } } ``` 在上面的代码,我们在doSomethingInNewThread方法创建了一个新的线程,并在其使用ThreadLocal来存储当前线程的session对象。在使用完后,我们及时关闭session并从ThreadLocal移除它。 需要注意的是,我们需要使用entityManager来获取当前线程的session对象,并且在使用完后需要手动关闭session。同时,我们在使用session进行懒加载操作时,需要使用Hibernate.initialize来强制进行加载。 希望这个示例代码能够帮助你解决懒加载No Session的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值