使用@Async 注解异步调用方法,注意事项,解决方案

异步调用方法

使用@Async @EnableAsync注解

使用:

1.在需要异步执行的方法上加上@Async注解
2.在Spring的启动类上加上@EnableAsync注解 否则异步不起作用
使用@Async 注解异步调用方法,注意事项,解决方案_第1张图片
使用@Async 注解异步调用方法,注意事项,解决方案_第2张图片

注意事项:

  1. 所使用的@Async注解方法的类对象应该是Spring容器管理的bean对象;
    使用@Async的方法,需要进行@Autowired引入进来或者new 创建一个对象。
  2. 不要在同一个类里面调用异步方法
    原因是如果调用方和被调用方是在同一个类中,是无法产生切面的,@Async没有被Spring容器管理
  3. 杜绝AopContext.currentProxy()
    AopContext.currentProxy()破坏了面向接口的编程,也包含了很多潜在的坑,应该禁用。要用异步就好好新建一个单独的异步类。
  4. 没有定义线程池
    如果不自定义异步方法的线程池默认使用SimpleAsyncTaskExecutor。SimpleAsyncTaskExecutor:不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。并发大的时候会产生严重的性能问题。
    基于上方demo,同学们可以搜索解决线程池使用Async的方案)
  5. 循环依赖问题
    在Spring 启动过程中Async注解为类创建代理类,这样Spring 三级缓存中就没有单例bean的早期引用对象而是Async代理对象,缓存里面找不到bean原始早期对象就引起报错。解决方法是为注入的其他类增加懒加载@Lazy注解,解决循环依赖报错问题。
  6. 异步处理@Async 拿不到 SpringSecurity 认证信息问题

问题原因:
使用@Async 注解异步调用方法,注意事项,解决方案_第3张图片
SpringSecurity 是线程绑定的 异步处理是重新new一个线程进行业务处理所以说 新线程里是没有 认证信息的

解决方案:
使用@Async 注解异步调用方法,注意事项,解决方案_第4张图片
需要重写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信息嘛,登陆信息获取不到对吧,那我给传过去不完了嘛,,机智如我。

使用@Async 注解异步调用方法,注意事项,解决方案_第5张图片

使用@Async 注解异步调用方法,注意事项,解决方案_第6张图片
或者我的这种不适合你们的场景,那你们可以看看https://markix.blog.csdn.net/article/details/106316479这篇文章或许可以有帮助

你可能感兴趣的:(解决方法,注解)