我希望将文件上传到AWS后uploadImage
方法完成,而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;
}
}
但这似乎仍在同步运行。这是什么问题?
答案 0 :(得分:1)
默认情况下,@Async
和其他@Transactional
这样的Spring方法级别注释仅在外部bean-to-bean方法调用上起作用。在同一bean中从uploadImage()
到scanFile()
的内部方法调用不会触发实现Spring行为的代理。根据Spring文档:
在代理模式(默认)下,仅拦截通过代理传入的外部方法调用。这意味着自调用实际上是目标对象中调用目标对象另一个方法的方法,即使调用的方法标记有@Transactional,也不会在运行时导致实际事务。另外,必须完全初始化代理以提供预期的行为,因此您不应在初始化代码(即@PostConstruct)中依赖此功能。
您可以配置AspectJ以在内部方法调用上启用注释,但是重构代码通常更容易。