package com.hotent.base.thread;

import java.util.concurrent.Executor;

import org.springframework.beans.factory.annotation.Value;
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.security.core.context.SecurityContextHolder;
import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor;
import org.springframework.web.servlet.DispatcherServlet;

@Configuration
@EnableAsync
public class AsyncConfiguration{
	public static final String THREAD_NAME = "asyncExecutor";
	
	@Value("${system.thread.core-pool-size:8}")
	private int corePoolSize;
	@Value("${system.thread.max-pool-size:8}")
	private int maxPoolSize;
	@Value("${system.thread.keep-alive-seconds:60}")
	private int keepAliveSeconds;
	@Value("${system.thread.queue-capacity:100}")
	private int queueCapacity;
	
	@Bean(name = THREAD_NAME)
	public Executor asyncExecutor(DispatcherServlet dispatcherServlet) {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);
		executor.setMaxPoolSize(maxPoolSize);
		executor.setQueueCapacity(queueCapacity);
		executor.setKeepAliveSeconds(keepAliveSeconds);
		executor.setWaitForTasksToCompleteOnShutdown(true);
		executor.setThreadNamePrefix("AsyncThread-");
		executor.initialize();
		// 解决SpringSecurity在异步线程中无法获取到当前登录用户的问题。
		SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
		// 异步线程无法获取父线程信息问题
		dispatcherServlet.setThreadContextInheritable(true);
		return new DelegatingSecurityContextAsyncTaskExecutor(executor);
	}
}
