在开发中经常会使用Spring的@Autowired来实现对象的自动注入,但是在最近的开发中在多线程中用Spring的@Autowired来自动注入时总是注入不进去,代码如下:
package com.common.base.utils.SpringUtils; import org.springframework.beans.factory.annotation.Autowired; import java.util.concurrent.atomic.AtomicInteger; public class ThreadRunner implements Runnable{ @Autowired private ServiceBean serviceBean; private static AtomicInteger count = new AtomicInteger(0); @Override public void run(){ if (serviceBean ==null){ return; } serviceBean.log(); count.addAndGet(1); System.out.println("当前线程为:" + Thread.currentThread().getName() + "count:" + count); } public ServiceBean getServiceBean() { return serviceBean; } public void setServiceBean(ServiceBean serviceBean) { this.serviceBean = serviceBean; } }
其中,ServiceBean定义如下:
package com.common.base.utils.SpringUtils; import org.springframework.stereotype.Service; @Service("serviceBean") public class ServiceBean{ public void log(){ System.out.println("this is service bean."); } }
只是简单的输出语句。然后在主线程中,启动线程,如下:
package com.common.base.utils.SpringUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath*:Service-*.xml"}) public class SpringMultiThreadTest{ @Test public void testSpringBean(){ for (int i=0; i<10000000; i++){ new Thread(new ThreadRunner()).start(); } try { Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } }
此时,不会有打印信息,serviceBean为空。
原因:在主线程中使用了:
new ThreadRunner()
新建了一个实例,并不在Spring容器中,也就没法获得Spring中的bean。
解决办法:
1、将ThreadRunner类也作为一个bean注入到spring容器中,如下:
package com.common.base.utils.SpringUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath*:Service-*.xml"}) public class SpringMultiThreadTest{ @Autowired private ThreadRunner threadRunner; @Test public void testSpringBean(){ for (int i=0; i<10000000; i++){ new Thread(threadRunner).start(); } try { Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } }
问题解决。
2、使用Spring手动获得ServiceBean,首先写一个手动获得Spring bean的工具类:
package com.common.base.utils.SpringUtils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; /** * 直接通过Spring 上下文获取SpringBean,用于多线程环境 * by jingquan @20160405 */ public class SpringBeanUtil implements ApplicationContextAware{ private static ApplicationContext applicationContext = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringBeanUtil.applicationContext = applicationContext; } public static Object getBeanByName(String beanName) { if (applicationContext == null){ return null; } return applicationContext.getBean(beanName); } public static <T> T getBean(Class<T> type) { return applicationContext.getBean(type); } }
然后在ThreadRunner类中不自动获取,而是手动获取,代码如下:
package com.common.base.utils.SpringUtils; import org.springframework.beans.factory.annotation.Autowired; import java.util.concurrent.atomic.AtomicInteger; public class ThreadRunner implements Runnable{ private ServiceBean serviceBean; private static AtomicInteger count = new AtomicInteger(0); public ThreadRunner(){ this.serviceBean = (ServiceBean)SpringBeanUtil.getBeanByName("serviceBean"); } @Override public void run(){ if (serviceBean ==null){ return; } serviceBean.log(); count.addAndGet(1); System.out.println("当前线程为:" + Thread.currentThread().getName() + "count:" + count); } public ServiceBean getServiceBean() { return serviceBean; } public void setServiceBean(ServiceBean serviceBean) { this.serviceBean = serviceBean; } }
问题解决。
相关推荐
本篇文章主要介绍了Spring 多线程下注入bean问题详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
二、使用单例引起线程安全问题的例子 那究竟什么时候会用到呢?我相信大多数人写的代码都不会去考虑这个事情,用spring就认为只有单例,也只习惯用单例。但是有时候你想将代码写得更优雅一些的时候,你不得不去思考...
这份宝典囊括了Java编程中的基础知识、多线程编程、数据库操作、Spring框架、Spring Boot、Spring Cloud、Linux操作系统、分布式系统、设计模式、面试指导以及自我介绍等内容。 基础部分,包括Java编程语言的核心...
主要介绍了详解SpringBoot 多线程处理任务 无法@Autowired注入bean问题解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
这个是spring 和 quartz的集成,quartz是单独的包,java线程的方式运行,利用自定义Jobfactory来解决spring注入service空指针的问题,简单实例执行main方法即可,很实用
多线程和并发操作 7.1.简介 7.2.线程本地存储 7.3.同步基础 7.3.1.ISync 7.3.2.SyncHolder 7.3.3.Latch 7.3.4.Semaphore 第八章. 对象池 8.1.简介 8.2.接口和实现 第九章. Spring.NET杂记 9.1.简介 9.2....
主要介绍了解决Spring session(redis存储方式)监听导致创建大量redisMessageListenerContailner-X线程问题,需要的朋友可以参考下
主要介绍了SpringBoot项目使用多线程处理任务时无法通过@Autowired注入bean问题的解决方法,需要的朋友可以参考下
10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的应对 10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼...
10.4.1 Spring通过单实例化Bean简化多线程问题 10.4.2 启动独立线程调用事务方法 10.5 联合军种作战的混乱 10.5.1 Spring事务管理器的应对 10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼...
- 多线程编程 2. 数据库: - 熟悉SQL语言 - 了解关系型数据库和非关系型数据库 - 数据库连接池 - 数据库事务 3. Spring框架: - Spring Boot - Spring MVC - Spring Data - Spring Security - Spring...
spring框架xml配置注入使用方式,用例利用spring容器创建对象使用技术:IOC控制反转
- 多线程编程 2. 数据库: - 熟悉SQL语言 - 了解关系型数据库和非关系型数据库 - 数据库连接池 - 数据库事务 3. Spring框架: - Spring Boot - Spring MVC - Spring Data - Spring Security - Spring...
- 多线程编程 2. 数据库: - 熟悉SQL语言 - 了解关系型数据库和非关系型数据库 - 数据库连接池 - 数据库事务 3. Spring框架: - Spring Boot - Spring MVC - Spring Data - Spring Security - Spring...
内容包括:Spring、SprngBoot、SpringCloud、Redis、MySQL、MyBatis、JVM、多线程和高并发、设计模式等 Spring框架:包括Spring的核心概念,如依赖注入和面向切面编程 Spring Boot:包括Spring Boot的基础知识,如...
Java开发基于多线程和NIO实现聊天室源码+项目说明(含服务端+客户端).zip 涉及到的技术点 - 线程池ThreadPoolExecutor - 阻塞队列BlockingQueue,生产者消费者模式 - Selector - Channel - ByteBuffer - ...
在项目中,Spring框架提供了依赖注入和面向切面编程的功能,可以提高代码的可维护性和可测试性。SpringMVC负责处理请求和响应,可以实现灵活的URL映射和请求处理。MyBatis或Hibernate可以简化数据库操作,提供了方便...
3.2 多线程 51 3.2.1 点睛 51 3.2.2 示例 51 3.3 计划任务 54 3.3.1 点睛 54 3.3.2 示例 54 3.4 条件注解@Conditional 56 3.4.1 点睛 56 3.4.2 示例 57 3.5 组合注解与元注解 60 3.5.1 点睛 60 3.5.2 示例 60 3.6 @...
但这个不是绝对的,考虑到多线程的特性,可能有时候不会使用缓存超时控制@DataProvider注解支持配置超时,超时将引发中断异常(InterruptedException),伴随异常处理逻辑使用方法1.配置pom.xml < dependency>