• -------------------------------------------------------------
  • ====================================

多线程中使用Spring的注入问题

springcloud dewbay 5年前 (2019-04-12) 2669次浏览 已收录 0个评论 扫描二维码


在开发中经常会使用 Spring 的@Autowired 来实现对象的自动注入,但是在最近的开发中在多线程中用 Spring 的@Autowired 来自动注入时总是注入不进去,代码如下:Java 代码  

多线程中使用Spring的注入问题
  1. package com.common.base.utils.SpringUtils;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4.   
  5. import java.util.concurrent.atomic.AtomicInteger;  
  6.   
  7. public class ThreadRunner implements Runnable{  
  8.   
  9.     @Autowired  
  10.     private ServiceBean serviceBean;  
  11.   
  12.     private static AtomicInteger count = new AtomicInteger(0);  
  13.   
  14.     @Override  
  15.     public void run(){  
  16.         if (serviceBean ==null){  
  17.             return;  
  18.         }  
  19.         serviceBean.log();  
  20.         count.addAndGet(1);  
  21.         System.out.println(“当前线程为:” + Thread.currentThread().getName() + “count:” + count);  
  22.     }  
  23.   
  24.     public ServiceBean getServiceBean() {  
  25.         return serviceBean;  
  26.     }  
  27.   
  28.     public void setServiceBean(ServiceBean serviceBean) {  
  29.         this.serviceBean = serviceBean;  
  30.     }  
  31. }  

 其中,ServiceBean 定义如下:Java 代码  

多线程中使用Spring的注入问题
  1. package com.common.base.utils.SpringUtils;  
  2.   
  3. import org.springframework.stereotype.Service;  
  4.   
  5. @Service(“serviceBean”)  
  6. public class ServiceBean{  
  7.   
  8.     public void log(){  
  9.         System.out.println(“this is service bean.”);  
  10.     }  
  11. }  

 只是简单的输出语句。然后在主线程中,启动线程,如下:Java 代码  

多线程中使用Spring的注入问题
  1. package com.common.base.utils.SpringUtils;  
  2.   
  3. import org.junit.Test;  
  4. import org.junit.runner.RunWith;  
  5. import org.springframework.test.context.ContextConfiguration;  
  6. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  7.   
  8. @RunWith(SpringJUnit4ClassRunner.class)  
  9. @ContextConfiguration(locations = {“classpath*:Service-*.xml”})  
  10. public class SpringMultiThreadTest{  
  11.     @Test  
  12.     public void testSpringBean(){  
  13.         for (int i=0; i<10000000; i++){  
  14.             new Thread(new ThreadRunner()).start();  
  15.         }  
  16.   
  17.         try {  
  18.             Thread.sleep(1000);  
  19.         }catch (InterruptedException e){  
  20.             e.printStackTrace();  
  21.         }  
  22.     }  
  23. }  

 此时,不会有打印信息,serviceBean 为空。

原因:在主线程中使用了:Java 代码  

多线程中使用Spring的注入问题
  1. new ThreadRunner()  

 新建了一个实例,并不在 Spring 容器中,也就没法获得 Spring 中的 bean。

解决办法:

1、将 ThreadRunner 类也作为一个 bean 注入到 spring 容器中,如下:Java 代码  

多线程中使用Spring的注入问题
  1. package com.common.base.utils.SpringUtils;  
  2.   
  3. import org.junit.Test;  
  4. import org.junit.runner.RunWith;  
  5. import org.springframework.beans.factory.annotation.Autowired;  
  6. import org.springframework.test.context.ContextConfiguration;  
  7. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  
  8.   
  9. @RunWith(SpringJUnit4ClassRunner.class)  
  10. @ContextConfiguration(locations = {“classpath*:Service-*.xml”})  
  11. public class SpringMultiThreadTest{  
  12.     @Autowired  
  13.     private ThreadRunner threadRunner;  
  14.     @Test  
  15.     public void testSpringBean(){  
  16.         for (int i=0; i<10000000; i++){  
  17.             new Thread(threadRunner).start();  
  18.         }  
  19.         try {  
  20.             Thread.sleep(1000);  
  21.         }catch (InterruptedException e){  
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25. }  

 问题解决。

2、使用 Spring 手动获得 ServiceBean,首先写一个手动获得 Spring bean 的工具类:Java 代码  

多线程中使用Spring的注入问题
  1. package com.common.base.utils.SpringUtils;  
  2.   
  3. import org.springframework.beans.BeansException;  
  4. import org.springframework.context.ApplicationContext;  
  5. import org.springframework.context.ApplicationContextAware;  
  6.   
  7. /** 
  8.  * 直接通过 Spring 上下文获取 SpringBean,用于多线程环境 
  9.  * by jingquan @20160405 
  10.  */  
  11.   
  12. public class SpringBeanUtil implements ApplicationContextAware{  
  13.       
  14.     private static ApplicationContext applicationContext = null;  
  15.   
  16.     @Override  
  17.     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
  18.         SpringBeanUtil.applicationContext = applicationContext;  
  19.     }  
  20.   
  21.     public static Object getBeanByName(String beanName) {  
  22.         if (applicationContext == null){  
  23.             return null;  
  24.         }  
  25.         return applicationContext.getBean(beanName);  
  26.     }  
  27.   
  28.     public static <T> T getBean(Class<T> type) {  
  29.         return applicationContext.getBean(type);  
  30.     }  
  31.   
  32. }  

 然后在 ThreadRunner 类中不自动获取,而是手动获取,代码如下:Java 代码  

多线程中使用Spring的注入问题
  1. package com.common.base.utils.SpringUtils;  
  2. import org.springframework.beans.factory.annotation.Autowired;  
  3. import java.util.concurrent.atomic.AtomicInteger;  
  4. public class ThreadRunner implements Runnable{  
  5.     private ServiceBean serviceBean;  
  6.     private static AtomicInteger count = new AtomicInteger(0);  
  7.     public ThreadRunner(){  
  8.         this.serviceBean = (ServiceBean)SpringBeanUtil.getBeanByName(“serviceBean”);  
  9.     }  
  10.     @Override  
  11.     public void run(){  
  12.         if (serviceBean ==null){  
  13.             return;  
  14.         }  
  15.         serviceBean.log();  
  16.         count.addAndGet(1);  
  17.         System.out.println(“当前线程为:” + Thread.currentThread().getName() + “count:” + count);  
  18.     }  
  19.   
  20.     public ServiceBean getServiceBean() {  
  21.         return serviceBean;  
  22.     }  
  23.   
  24.     public void setServiceBean(ServiceBean serviceBean) {  
  25.         this.serviceBean = serviceBean;  
  26.     }  
  27. }  

 问题解决。


露水湾 , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:多线程中使用Spring的注入问题
喜欢 (0)
[]
分享 (0)
关于作者:
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址