Java多线程中调用Spring的Bean三种实现方式
- 工作小总结
- 时间:2023-05-17 15:37
- 2986人已阅读
简介
一、背景 工作中我们想写个线程是很简单的,方式也很多,我在之前的文章Java实现多线程方式详解也介绍过,就不多讲了,但是实际工作中,尤其是采用spirng注解的方式的情况下,有时我们就要在线程中调用Spring的Bean,很多小伙伴还不知道怎么处理,我们今天就来聊聊Java多线程中调用Spring的Bean的几种方式,本文中SpringBoot版本为2.5.2,JDK环境为1.8,本文中使用到的
🔔🔔🔔好消息!好消息!🔔🔔🔔
有需要的朋友👉:联系凯哥
一、背景
工作中我们想写个线程是很简单的,方式也很多,我在之前的文章Java实现多线程方式详解也介绍过,就不多讲了,但是实际工作中,尤其是采用spirng注解的方式的情况下,有时我们就要在线程中调用Spring的Bean,很多小伙伴还不知道怎么处理,我们今天就来聊聊Java多线程中调用Spring的Bean的几种方式,本文中Spring Boot版本为2.5.2,JDK环境为 1.8,本文中使用到的依赖如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.5.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.14</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>compile</scope> </dependency>
本文使用@PostConstruct 进行测试,@PostConstruct 是一个java的注解,它修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次。
二、方式一:实现ApplicationContextAware接口
当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean。前提是该类上有IOC相关注解才会生效,例如@Component(当然使用xml配置的bean信息也可以)
2.1、工具类
SpringBeanUtil.java
package com.alian.multithread.common;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringBeanUtil implements ApplicationContextAware {
//定义静态ApplicationContext
private static ApplicationContext applicationContext;
//重写接口的方法,该方法在启动项目的时候会自动执行
//该类上有IOC相关注解才会生效,例如@Component
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
//通过beanName获取Bean
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
return (T) applicationContext.getBean(beanName);
}
//通过beanClass获取Bean
public static <T> T getBean(Class<T> beanClass) {
return applicationContext.getBean(beanClass);
}
}2.2、发送短信服务类
package com.alian.multithread.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class PushSmsService {
public void pushSms() {
log.info("推送短信服务子线程【{}】执行", Thread.currentThread().getName());
}
}2.3、发送短信线程类
package com.alian.multithread.thread;
import com.alian.multithread.common.SpringBeanUtil;
import com.alian.multithread.service.PushSmsService;
public class PushSmsRunnable implements Runnable{
@Override
public void run() {
//获取到我们需要的bean
PushSmsService pushSmsService = SpringBeanUtil.getBean(PushSmsService.class);
pushSmsService.pushSms();
}
}2.4、发送短信测试
package com.alian.multithread.service;
import com.alian.multithread.thread.PushSmsRunnable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Slf4j
@Service
public class TestPushSmsService {
@PostConstruct
public void testPushSms() {
for (int i = 0; i < 3; i++) {
Thread thread = new Thread(new PushSmsRunnable());
thread.start();
}
}
}
运行结果:

三、方式二:线程内部构造方法
3.1、发送邮件服务类
package com.alian.multithread.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class SendEmailService {
public void sendEmail() {
log.info("发送邮件服务子线程【{}】执行", Thread.currentThread().getName());
}
}3.2、发送邮件线程类
package com.alian.multithread.thread;
import com.alian.multithread.service.SendEmailService;
public class SendEmailRunnable implements Runnable{
private SendEmailService sendEmailService;
public SendEmailRunnable(SendEmailService sendEmailService){
this.sendEmailService=sendEmailService;
}
@Override
public void run() {
sendEmailService.sendEmail();
}
}3.3、发送邮件测试
package com.alian.multithread.service;
import com.alian.multithread.thread.SendEmailRunnable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Slf4j
@Service
public class TestSendEmailService {
@Autowired
private SendEmailService sendEmailService;
@PostConstruct
public void testSendEmail() {
for (int i = 0; i < 4; i++) {
Thread thread = new Thread(new SendEmailRunnable(sendEmailService));
thread.start();
}
}
}运行结果:

四、方式三:内部类(推荐)
4.1、个性化服务类
package com.alian.multithread.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class PersonalService {
public void personalBuss() {
log.info("个性化服务子线程【{}】执行", Thread.currentThread().getName());
}
}4.2、个性化服务类测试
package com.alian.multithread.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Slf4j
@Service
public class TestPersonalService {
@Autowired
private PersonalService personalService;
@PostConstruct
public void execute() {
for (int i = 0; i < 5; i++) {
new PersonalThread().start();
}
}
private class PersonalThread extends Thread {
@Override
public void run() {
TestPersonalService.this.personalService.personalBuss();
}
}
}