Amazon web services Spring Boot@Async不工作
我希望Amazon web services Spring Boot@Async不工作,amazon-web-services,spring-boot,asynchronous,Amazon Web Services,Spring Boot,Asynchronous,我希望uploadImage方法在文件上传到AWS后完成,而scanFile方法仍在后台异步运行 @RestController public class EmailController { @PostMapping("/upload") @ResponseStatus(HttpStatus.OK) public void uploadImage(@RequestParam MultipartFile photos) { awsAPIService.upl
uploadImage
方法在文件上传到AWS后完成,而scanFile
方法仍在后台异步运行
@RestController
public class EmailController {
@PostMapping("/upload")
@ResponseStatus(HttpStatus.OK)
public void uploadImage(@RequestParam MultipartFile photos) {
awsAPIService.uploadImage(photos);
}
}
...
@Service
public class AwsAPIService {
public void uploadImage(MultipartFile file) {
try {
File fileToUpload = this.convertMultiPartToFile(file);
String fileName = this.generateFileName(file);
s3client.putObject(new PutObjectRequest(AWS_S3_QUARANTINE_BUCKET_NAME,fileName, fileToUpload));
fileToUpload.delete();
// start scan file
scanFile();
} ...
}
@Async
public void scanFile() {
log.info("Start scanning");
String queueUrl = sqs.getQueueUrl("bucket-antivirus").getQueueUrl();
List<Message> messages = sqs.receiveMessage(new ReceiveMessageRequest().withQueueUrl(queueUrl)
.withWaitTimeSeconds(20)).getMessages();
for (Message message : messages) {
// delete message
...
}
}
}
...
@EnableAsync
public class AppConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(200);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}
@RestController
公共类电子邮件控制器{
@后映射(“/upload”)
@ResponseStatus(HttpStatus.OK)
public void uploadImage(@RequestParam MultipartFile photos){
上传图片(照片);
}
}
...
@服务
公共类自动售货机{
公共无效上载映像(多部分文件){
试一试{
File fileToUpload=this.convertMultiPartToFile(文件);
字符串文件名=this.generateFileName(文件);
s3client.putObject(新的PutObjectRequest(AWS_S3_隔离_BUCKET_名称、文件名、fileToUpload));
fileToUpload.delete();
//启动扫描文件
扫描文件();
} ...
}
@异步的
公共void扫描文件(){
日志信息(“开始扫描”);
字符串queueUrl=sqs.getQueueUrl(“bucket antivirus”).getQueueUrl();
List messages=sqs.receiveMessage(new ReceiveMessageRequest().withQueueUrl(queueUrl)
.withWaitTimeSeconds(20)).getMessages();
用于(消息:消息){
//删除消息
...
}
}
}
...
@使能同步
公共类AppConfig{
@豆子
公共任务执行器任务执行器(){
ThreadPoolTaskExecutor taskExecutor=新的ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(200);
taskExecutor.AfterPropertieSet();
返回任务执行器;
}
}
但这似乎仍在同步运行。这里的问题是什么?默认情况下
@Async
和其他Spring方法级别的注释,如@Transactional
只在外部的bean-to-bean方法调用上工作。同一bean中从uploadImage()
到scanFile()
的内部方法调用不会触发实现Spring行为的代理。根据Spring文档:
在代理模式(这是默认模式)下,只截获通过代理传入的外部方法调用。这意味着自调用,实际上是目标对象内调用目标对象另一个方法的方法,即使调用的方法标记为@Transactional,在运行时也不会导致实际事务。此外,代理必须完全初始化以提供预期的行为,因此您不应在初始化代码中依赖此功能,即@PostConstruct
您可以将AspectJ配置为在内部方法调用上启用注释,但重构代码通常更容易。谢谢,我可以问一下,我应该如何重构代码,使其成为
scanFile
方法的外部调用吗?@Cosaic一种方法是从@Controller
调用awsapiersevice.scanFile()
,就在awsAPIService.uploadImage(photos)
之后。为什么通过将其从服务类移动到控制器类,不再将其视为内部调用?@Cosaic内部调用在同一个bean中的方法之间进行,两个不同bean之间的任何调用都是外部的。如果我在异步方法中添加另一个方法调用,这个方法是异步的吗?我是否仍应为该方法添加@async
?