最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring中的@Async原理分析

 更新時間:2024年01月09日 09:00:12   作者:it_lihongmin  
這篇文章主要介紹了Spring中的@Async原理分析,自定義new ThreadPoolExecutor并調(diào)用invokeAll等進行并發(fā)編程,后面發(fā)現(xiàn)只要在方法上添加@Async注解,并使用@EnableAsync進行開啟默認會使用SimpleAsyncTaskExecutor類型,需要的朋友可以參考下

前言

之前編程都是自定義new ThreadPoolExecutor(。。。),并調(diào)用invokeAll等進行并發(fā)編程。

后面發(fā)現(xiàn)只要在方法上添加@Async注解,并使用@EnableAsync進行開啟,并且@since為Spring 3.1版本。

我使用的Spring 5版本的,默認會使用SimpleAsyncTaskExecutor類型。就是一個大坑。

1、@Async

@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {
 
    Class<? extends Annotation> annotation() default Annotation.class;
 
    boolean proxyTargetClass() default false;
 
    AdviceMode mode() default AdviceMode.PROXY;
 
    int order() default Ordered.LOWEST_PRECEDENCE;
}

與之前分析@EnableTransactionManagement一樣,屬性都差不多。使用@Import方式將AsyncConfigurationSelector注冊為bean。

實現(xiàn)了ImportSelector接口 

public String[] selectImports(AdviceMode adviceMode) {
    switch (adviceMode) {
        case PROXY:
            return new String[] {ProxyAsyncConfiguration.class.getName()};
        case ASPECTJ:
            return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
        default:
            return null;
    }
}

@EnableAsync上沒有配置mode,則默認使用jdk方式實現(xiàn)。返回ProxyAsyncConfiguration將其注入為bean。

2、ProxyAsyncConfiguration

1)、實現(xiàn)ImportAware

則在ProxyAsyncConfiguration初始化為bean時,會進行回調(diào),實現(xiàn)方法如下:

public void setImportMetadata(AnnotationMetadata importMetadata) {
	this.enableAsync = AnnotationAttributes.fromMap(
			importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
	if (this.enableAsync == null) {
		throw new IllegalArgumentException(
				"@EnableAsync is not present on importing class " + 
           importMetadata.getClassName());
	}
}

獲取@EnableAsync注解上的配置信息,并保存到 enableAsync屬性中。

2)、AsyncAnnotationBeanPostProcessor

將 AsyncAnnotationBeanPostProcessor初始化為bean

@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
	Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
	AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
	bpp.configure(this.executor, this.exceptionHandler);
	Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
	if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class,
         "annotation")) {
		bpp.setAsyncAnnotationType(customAsyncAnnotation);
	}
	bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
	bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
	return bpp;
}

3、AsyncAnnotationBeanPostProcessor

實現(xiàn)了很多Aware接口,注入了BeanFactory和BeanClassLoader,主要是在setBeanFactory方法中:

public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
 
    AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
    if (this.asyncAnnotationType != null) {
        advisor.setAsyncAnnotationType(this.asyncAnnotationType);
    }
    advisor.setBeanFactory(beanFactory);
    this.advisor = advisor;
}

new 了一個AsyncAnnotationAdvisor,而線程池和異常處理器是從初始化 ProxyAsyncConfiguration時傳入的,默認都為null。構(gòu)造器如下:

public AsyncAnnotationAdvisor(@Nullable Supplier<Executor> executor, 
    @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
 
    Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
    asyncAnnotationTypes.add(Async.class);
    try {
        asyncAnnotationTypes.add((Class<? extends Annotation>)
        ClassUtils.forName("javax.ejb.Asynchronous", 
        AsyncAnnotationAdvisor.class.getClassLoader()));
    } catch (ClassNotFoundException ex) {
    // If EJB 3.1 API not present, simply ignore.
    }
    this.advice = buildAdvice(executor, exceptionHandler);
    this.pointcut = buildPointcut(asyncAnnotationTypes);
}

buildAdvice:構(gòu)建攔截器

protected Advice buildAdvice(@Nullable Supplier<Executor> executor, 
    @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
 
    AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
    interceptor.configure(executor, exceptionHandler);
    return interceptor;
}

初始化了一個AnnotationAsyncExecutionInterceptor 攔截器,后續(xù)進行分析。使用有參構(gòu)造,但是異步任務(wù)的線程池為null。

buildPointcut:根據(jù)Async構(gòu)建攔截匹配點

protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
    ComposablePointcut result = null;
    // asyncAnnotationTypes默認只要Async類型
    for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
        Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
        Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
        if (result == null) {
            // result肯定是null,先添加Class類型的切點匹配器
            result = new ComposablePointcut(cpc);
        } else {
            result.union(cpc);
        }
        // 再添加Method類型的切點攔截器
        result = result.union(mpc);
    }
    return (result != null ? result : Pointcut.TRUE);
}

默認情況下 asyncAnnotationTypes中只要Async類型,則初始化了配置Async的類和方法的 匹配攔截器(AnnotationMatchingPointcut),并且都添加到ComposablePointcut中。

一切初始化完成后,在每個bean的生命周期都會進行回調(diào) postProcessAfterInitialization方法:

public Object postProcessAfterInitialization(Object bean, String beanName) {
	if (this.advisor == null || bean instanceof AopInfrastructureBean) {
		// Ignore AOP infrastructure such as scoped proxies.
		return bean;
	}
 
	if (bean instanceof Advised) {
		Advised advised = (Advised) bean;
		if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
			// Add our local Advisor to the existing proxy's Advisor chain...
			if (this.beforeExistingAdvisors) {
				advised.addAdvisor(0, this.advisor);
			}
			else {
				advised.addAdvisor(this.advisor);
			}
			return bean;
		}
	}
 
	if (isEligible(bean, beanName)) {
		ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
		if (!proxyFactory.isProxyTargetClass()) {
			evaluateProxyInterfaces(bean.getClass(), proxyFactory);
		}
		proxyFactory.addAdvisor(this.advisor);
		customizeProxyFactory(proxyFactory);
		return proxyFactory.getProxy(getProxyClassLoader());
	}
 
	// No proxy needed.
	return bean;
}
protected ProxyFactory prepareProxyFactory(Object bean, String beanName) {
    ProxyFactory proxyFactory = new ProxyFactory();
    proxyFactory.copyFrom(this);
    proxyFactory.setTarget(bean);
    return proxyFactory;
}

4、AnnotationAsyncExecutionInterceptor

顯然核心實現(xiàn)在 invoke方法中:

public Object invoke(final MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
    final Method userDeclaredMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
 
    AsyncTaskExecutor executor = determineAsyncExecutor(userDeclaredMethod);
    if (executor == null) {
        throw new IllegalStateException(
			"No executor specified and no default executor set on " +
            " AsyncExecutionInterceptor either");
    }
 
    Callable<Object> task = () -> {
        try {
            Object result = invocation.proceed();
            if (result instanceof Future) {
                return ((Future<?>) result).get();
            }
        } catch (ExecutionException ex) {
            handleError(ex.getCause(), userDeclaredMethod, invocation.getArguments());
        } catch (Throwable ex) {
            handleError(ex, userDeclaredMethod, invocation.getArguments());
        }
        return null;
    };
    return doSubmit(task, executor, invocation.getMethod().getReturnType());
}

先獲取執(zhí)行的方法信息,再判斷執(zhí)行的異步線程池,再講任務(wù)提交給線程池。

1)、獲取線程池(determineAsyncExecutor)

之前初始化的時候,傳入的線程池為null,則:

public AsyncExecutionAspectSupport(@Nullable Executor defaultExecutor) {
	this.defaultExecutor = new SingletonSupplier<>(defaultExecutor, () -> getDefaultExecutor(this.beanFactory));
	this.exceptionHandler = SingletonSupplier.of(SimpleAsyncUncaughtExceptionHandler::new);
}
protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
	if (beanFactory != null) {
		try {
			// Search for TaskExecutor bean... not plain Executor since that would
			// match with ScheduledExecutorService as well, which is unusable for
			// our purposes here. TaskExecutor is more clearly designed for it.
			return beanFactory.getBean(TaskExecutor.class);
		}
		catch (NoUniqueBeanDefinitionException ex) {
			logger.debug("Could not find unique TaskExecutor bean", ex);
			try {
				return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
			}
			catch (NoSuchBeanDefinitionException ex2) {
				if (logger.isInfoEnabled()) {
					logger.info("More than one TaskExecutor bean found within the context, and none is named " +
							"'taskExecutor'. Mark one of them as primary or name it 'taskExecutor' (possibly " +
							"as an alias) in order to use it for async processing: " + ex.getBeanNamesFound());
				}
			}
		}
		catch (NoSuchBeanDefinitionException ex) {
			logger.debug("Could not find default TaskExecutor bean", ex);
			try {
				return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
			}
			catch (NoSuchBeanDefinitionException ex2) {
				logger.info("No task executor bean found for async processing: " +
						"no bean of type TaskExecutor and no bean named 'taskExecutor' either");
			}
			// Giving up -> either using local default executor or none at all...
		}
	}
	return null;
}

beanFactory.getBean(TaskExecutor.class)

最后是獲取了BeanFactory中的TaskExecutor的子類的bean(可能不存在)。

protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
    AsyncTaskExecutor executor = this.executors.get(method);
    if (executor == null) {
        Executor targetExecutor;
        String qualifier = getExecutorQualifier(method);
        if (StringUtils.hasLength(qualifier)) {
            targetExecutor = findQualifiedExecutor(this.beanFactory, qualifier);
        } else {
            targetExecutor = this.defaultExecutor.get();
        }
        if (targetExecutor == null) {
            return null;
        }
        executor = (targetExecutor instanceof AsyncListenableTaskExecutor ?
            (AsyncListenableTaskExecutor) targetExecutor : new 
                 TaskExecutorAdapter(targetExecutor));
        this.executors.put(method, executor);
    }
    return executor;
}

使用本地緩存ConcurrentHashMap, key為Methed, value為線程池。

1、先獲取執(zhí)行的方法的@Async的value值

protected String getExecutorQualifier(Method method) {
    // Maintainer's note: changes made here should also be made in
    // AnnotationAsyncExecutionAspect#getExecutorQualifier
    Async async = AnnotatedElementUtils.findMergedAnnotation(method, Async.class);
    if (async == null) {
        async = AnnotatedElementUtils.findMergedAnnotation(method.getDeclaringClass(), Async.class);
    }
    return (async != null ? async.value() : null);
}

如果獲取到配置的值(如定義方法時為:@Async("order") ),則獲取正在的線程池

protected Executor findQualifiedExecutor(@Nullable BeanFactory beanFactory, String qualifier) {
    if (beanFactory == null) {
        throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() +
					" to access qualified executor '" + qualifier + "'");
    }
    return BeanFactoryAnnotationUtils.qualifiedBeanOfType(beanFactory, Executor.class, qualifier);
}

2、如果@Async上沒有配置,則獲取默認值

 targetExecutor = this.defaultExecutor.get();

就是之前從BeanFactory中獲取TaskExecutor.class類型的實現(xiàn),當(dāng)前版本為spring5,,獲取到的類型為SimpleAsyncTaskExecutor

2)、執(zhí)行任務(wù)(doSubmit)

protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, 
    Class<?> returnType) {
    
    if (completableFuturePresent) {
        Future<Object> result = AsyncExecutionAspectSupport.CompletableFutureDelegate
        .processCompletableFuture(returnType, task, executor);
        if (result != null) {
            return result;
        }
    }
 
    if (ListenableFuture.class.isAssignableFrom(returnType)) {
        return ((AsyncListenableTaskExecutor)executor).submitListenable(task);
    } else if (Future.class.isAssignableFrom(returnType)) {
        return executor.submit(task);
    } else {
        executor.submit(task);
        return null;
    }
}

根據(jù)我們定義的方法的返回值進行處理,返回值可以是 null、Future、Spring的AsyncResult是ListenableFuture的子類。

5、SimpleAsyncTaskExecutor

如果使用@Async沒有配置線程池,并且沒有給AnnotationAsyncExecutionInterceptor設(shè)置線程池,則調(diào)用時就是一個坑,每次創(chuàng)建一個線程。

submit()方法:

@Override
public <T> Future<T> submit(Callable<T> task) {
    FutureTask<T> future = new FutureTask<>(task);
    execute(future, TIMEOUT_INDEFINITE);
    return future;
}

execute()執(zhí)行方法:

@Override
public void execute(Runnable task, long startTimeout) {
    Assert.notNull(task, "Runnable must not be null");
    Runnable taskToUse = (this.taskDecorator != null ? this.taskDecorator.decorate(task) : task);
    if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
        this.concurrencyThrottle.beforeAccess();
        doExecute(new ConcurrencyThrottlingRunnable(taskToUse));
    } else {
        doExecute(taskToUse);
    }
}

doExecute()方法:

protected void doExecute(Runnable task) {
    Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) 
        : createThread(task));
    thread.start();
}
public Thread createThread(Runnable runnable) {
    Thread thread = new Thread(getThreadGroup(), runnable, nextThreadName());
    thread.setPriority(getThreadPriority());
    thread.setDaemon(isDaemon());
    return thread;
}

是否初始化了線程工廠,有則用工廠進行new,否則還是new。也就是說只要使用默認SimpleAsyncTaskExecutor線程池,每次執(zhí)行任務(wù)就new一個新的線程。

到此這篇關(guān)于Spring中的@Async原理分析的文章就介紹到這了,更多相關(guān)@Async原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java源碼解析ConcurrentHashMap的初始化

    Java源碼解析ConcurrentHashMap的初始化

    今天小編就為大家分享一篇關(guān)于Java源碼解析ConcurrentHashMap的初始化,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Java 實戰(zhàn)項目錘煉之樸素風(fēng)格個人博客系統(tǒng)的實現(xiàn)流程

    Java 實戰(zhàn)項目錘煉之樸素風(fēng)格個人博客系統(tǒng)的實現(xiàn)流程

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java+vue+Springboot+ssm+mysql+maven+redis實現(xiàn)一個樸素風(fēng)格的個人博客系統(tǒng),大家可以在過程中查缺補漏,提升水平
    2021-11-11
  • SpringBoot在接收參數(shù)的七種方式詳解

    SpringBoot在接收參數(shù)的七種方式詳解

    這篇文章主要介紹了SpringBoot在接收參數(shù)的七種方式詳解,隨著前后端的分離,接口方式開發(fā)成為普遍的開發(fā)形式,前端相對于后端來說,常用的接口傳參方式就一定要了解和熟悉,下面?我們梳理了常用的七種?Controller層接受參數(shù)的方式,需要的朋友可以參考下
    2023-10-10
  • 解決httpServletRequest.getParameter獲取不到參數(shù)的問題

    解決httpServletRequest.getParameter獲取不到參數(shù)的問題

    這篇文章主要介紹了解決httpServletRequest.getParameter獲取不到參數(shù)的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 關(guān)于SpringMVC在Controller層方法的參數(shù)解析詳解

    關(guān)于SpringMVC在Controller層方法的參數(shù)解析詳解

    在SpringMVC中,控制器Controller負責(zé)處理由DispatcherServlet分發(fā)的請求,下面這篇文章主要給大家介紹了關(guān)于SpringMVC在Controller層方法的參數(shù)解析的相關(guān)資料,需要的朋友可以參考下
    2021-12-12
  • 關(guān)于SpringBoot簡介、官網(wǎng)構(gòu)建、快速啟動的問題

    關(guān)于SpringBoot簡介、官網(wǎng)構(gòu)建、快速啟動的問題

    SpringBoot 是由Pivotal團隊提供的全新框架,其設(shè)計目的是用來簡化Spring應(yīng)用的初始搭建以及開發(fā)過程,這篇文章主要介紹了SpringBoot簡介、官網(wǎng)構(gòu)建、快速啟動,需要的朋友可以參考下
    2022-07-07
  • 設(shè)計模式之責(zé)任鏈模式_動力節(jié)點Java學(xué)院整理

    設(shè)計模式之責(zé)任鏈模式_動力節(jié)點Java學(xué)院整理

    這篇文章主要為大家詳細介紹了設(shè)計模式之責(zé)任鏈模式的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • idea導(dǎo)入module全流程

    idea導(dǎo)入module全流程

    這篇文章主要介紹了idea導(dǎo)入module全流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java保留兩位小數(shù)的實現(xiàn)方法

    Java保留兩位小數(shù)的實現(xiàn)方法

    這篇文章主要介紹了 Java保留兩位小數(shù)的實現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Java面向?qū)ο笾^承的概念詳解

    Java面向?qū)ο笾^承的概念詳解

    這篇文章主要介紹了Java面向?qū)ο笾^承的概念詳解,Java是一種面向?qū)ο蟮木幊陶Z言,繼承是實現(xiàn)面向?qū)ο缶幊痰幕A(chǔ)之一。通過繼承,我們可以使代碼更具可讀性、可重用性和可維護性,從而提高程序的效率和可靠性,需要的朋友可以參考下
    2023-04-04

最新評論

玉环县| 禹城市| 桃园县| 台湾省| 文安县| 横峰县| 清原| 清流县| 白山市| 长沙县| 天峨县| 花莲县| 高碑店市| 盈江县| 石台县| 龙胜| 平泉县| 汶川县| 闽侯县| 南木林县| 温泉县| 新乡县| 新巴尔虎右旗| 临武县| 福建省| 张家川| 沅陵县| 扶余县| 福州市| 榆树市| 文成县| 洛南县| 武威市| 延川县| 柳林县| 青神县| 新竹市| 孝昌县| 隆昌县| 弥渡县| 荆州市|