异步调用方法
使用@Async @EnableAsync注解
使用:
1.在需要异步执行的方法上加上@Async注解
2.在Spring的启动类上加上@EnableAsync注解 否则异步不起作用
注意事项:
- 所使用的@Async注解方法的类对象应该是Spring容器管理的bean对象;
使用@Async的方法,需要进行@Autowired引入进来或者new 创建一个对象。 - 不要在同一个类里面调用异步方法
原因是如果调用方和被调用方是在同一个类中,是无法产生切面的,@Async没有被Spring容器管理 - 杜绝AopContext.currentProxy()
AopContext.currentProxy()破坏了面向接口的编程,也包含了很多潜在的坑,应该禁用。要用异步就好好新建一个单独的异步类。 - 没有定义线程池
如果不自定义异步方法的线程池默认使用SimpleAsyncTaskExecutor。SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。并发大的时候会产生严重的性能问题。
基于上方demo,同学们可以搜索解决线程池使用Async的方案) - 循环依赖问题
在Spring 启动过程中Async注解为类创建代理类,这样Spring 三级缓存中就没有单例bean的早期引用对象而是Async代理对象,缓存里面找不到bean原始早期对象就引起报错。解决方法是为注入的其他类增加懒加载@Lazy注解,解决循环依赖报错问题。 - 异步处理@Async 拿不到 SpringSecurity 认证信息问题
问题原因:
SpringSecurity 是线程绑定的 异步处理是重新new一个线程进行业务处理所以说 新线程里是没有 认证信息的
解决方案:
需要重写AsyncConfigurer 使用SpringSecurity 的 装饰线程池 这样就可以携带认证信息了
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
import org.springframework.stereotype.Component;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* @ClassName AsyncConfig
* @Description
* @Author xiang
* @Date 2021/4/30 18:19
**/
@Component
public class AsyncConfig extends AsyncConfigurerSupport {
/**
* 异步执行需要使用权限框架自带的包装线程池 保证权限信息的传递
*/
@Override
public Executor getAsyncExecutor() {
return new DelegatingSecurityContextExecutorService(Executors.newFixedThreadPool(5));
}
需要引入的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
但是这里小翔遇到一个问题,当万事俱备只欠东风的时候,我本地起项目,然后使用postman 调用相应的接口,没反应 压根儿就没进方法。无论我重启,寻找任何方案,甚至查看了postman接口地址,我把参数,地址等全发给同事他们可以调,所以就是我的问题了,求医无果,可能是人品问题吧。索性我就换了另一种简练的方式。
自己做的方案:
异步的方法不是没有token信息嘛,登陆信息获取不到对吧,那我给传过去不完了嘛,😏,机智如我。
或者我的这种不适合你们的场景,那你们可以看看https://markix.blog.csdn.net/article/details/106316479这篇文章或许可以有帮助
转载:https://blog.csdn.net/cdliker/article/details/116497738
查看评论