HeavenTang

导航

spring 异步处理导出 @Async @EnableAspectJAutoProxy 上下文

1启动类加上注解
@Configuration
@EnableAsync
@EnableAspectJAutoProxy(exposeProxy = true)

如:

2、
使用@Async 放在 @service类下面的方法上。
注意,主线程和异步方法在同一个类里面, 需要手动获取bean代理,AopContext.currentProxy, 同时主线程加上注解@Transactional, 如果不加这个注解,即使启动类加了EnableAspectJAutoProxy也不会起作用。
r如:
// 异步处理
((EvaluationTaskMonitorServiceImpl) AopContext.currentProxy()).newCreateStudentExportData(
pageQueryParam, map, evaluationRoleName, user, scopeCodes
, fileName, userAgent, characterEncoding, os, attachmentProcessCode);

注意:如果主线程和异步方法不在同一个类里面,直接加@Async在需要异步的类的方法上就可以,不需要手动获取代理

3、如果异步方法里面使用了上下文,httprequest或者httpResponse, 那么是获取不到的。需要加一个线程类,再手动使用。

点击查看代码
package com.ly.education.teaching.assessment.server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

@Configuration
@EnableAsync
public class AsyncConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(AsyncConfiguration.class);

    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();

        // 核心线程数:线程池创建时候初始化的线程数
        taskExecutor.setCorePoolSize(10);

        // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        taskExecutor.setMaxPoolSize(20);

        // 缓冲队列:用来缓冲执行任务的队列
        taskExecutor.setQueueCapacity(50);

        // 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁
        taskExecutor.setKeepAliveSeconds(60);

        // 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
        taskExecutor.setThreadNamePrefix("HiTask-");

        // 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)
        //taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
        taskExecutor.initialize();

        //解决使用@Async注解,获取不到上下文信息的问题 这样http的就能获取到了
        taskExecutor.setTaskDecorator(runnable -> {
            RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
            return ()->{
                try {
                    // 我们set 进去 ,其实是一个ThreadLocal维护的.
                    RequestContextHolder.setRequestAttributes(requestAttributes);
                    runnable.run();
                } finally {
                    // 最后记得释放内存
                    RequestContextHolder.resetRequestAttributes();
                }
            };

        });

        return taskExecutor;
    }

    class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {

        @Override
        public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
            logger.error("MethodName={},Throwable={}",method.getName(),throwable.toString());
        }
    }



}

点击查看代码
 // @Async 的方法使用http上下文是获取不到的,需加AsyncConfiguration这个类,使用RequestContextHolder方式获取
        ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request1 = attrs.getRequest();
        HttpServletResponse response1 = attrs.getResponse();

posted on 2025-06-19 14:04  HeavenTang  阅读(76)  评论(0)    收藏  举报