• SpringFramework 之EnableAsync


    EnableAsync

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AsyncConfigurationSelector.class)
    public @interface EnableAsync {
    
    	/**
    	 * Indicate the 'async' annotation type to be detected at either class
    	 * or method level.
    	 * 

    By default, both Spring's @{@link Async} annotation and the EJB 3.1 * {@code @javax.ejb.Asynchronous} annotation will be detected. *

    This attribute exists so that developers can provide their own * custom annotation type to indicate that a method (or all methods of * a given class) should be invoked asynchronously. */ Class<? extends Annotation> annotation() default Annotation.class; /** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. *

    Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}. *

    The default is {@code false}. *

    Note that setting this attribute to {@code true} will affect all * Spring-managed beans requiring proxying, not just those marked with {@code @Async}. * For example, other beans marked with Spring's {@code @Transactional} annotation * will be upgraded to subclass proxying at the same time. This approach has no * negative impact in practice unless one is explicitly expecting one type of proxy * vs. another — for example, in tests. */ boolean proxyTargetClass() default false; /** * Indicate how async advice should be applied. *

    The default is {@link AdviceMode#PROXY}. * Please note that proxy mode allows for interception of calls through the proxy * only. Local calls within the same class cannot get intercepted that way; an * {@link Async} annotation on such a method within a local call will be ignored * since Spring's interceptor does not even kick in for such a runtime scenario. * For a more advanced mode of interception, consider switching this to * {@link AdviceMode#ASPECTJ}. */ AdviceMode mode() default AdviceMode.PROXY; /** * Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor} * should be applied. *

    The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run * after all other post-processors, so that it can add an advisor to * existing proxies rather than double-proxy. */ int order() default Ordered.LOWEST_PRECEDENCE; }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    1, either a unique org.springframework.core.task.TaskExecutor bean in the context,
    2, java.util.concurrent.Executor bean named “taskExecutor” otherwise
    3, a org.springframework.core.task.SimpleAsyncTaskExecutor will be used to process async method invocations

    注意,如果什么都不配置, 那么SimpleAsyncTaskExecutor 就会被创建
    NOTE: This implementation does not reuse threads! Consider a thread-pooling TaskExecutor implementation instead, in particular for executing a large number of short-lived tasks.

    spring对pool做了很多抽象, 参见org.springframework.core.task.TaskExecutor

    4,使用AsyncConfigurer或者 AsyncConfigurerSupport自定义配置

    public interface AsyncConfigurer {
    
    	/**
    	 * The {@link Executor} instance to be used when processing async
    	 * method invocations.
    	 */
    	@Nullable
    	default Executor getAsyncExecutor() {
    		return null;
    	}
    
    	/**
    	 * The {@link AsyncUncaughtExceptionHandler} instance to be used
    	 * when an exception is thrown during an asynchronous method execution
    	 * with {@code void} return type.
    	 */
    	@Nullable
    	default AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    		return null;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    AsyncConfigurationSelector

    public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
    
    	private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
    			"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
    
    
    	/**
    	 * Returns {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration}
    	 * for {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()},
    	 * respectively.
    	 */
    	@Override
    	@Nullable
    	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;
    		}
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    这个AdviceModeImportSelector很值得研究

    public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
    
    	/**
    	 * The default advice mode attribute name.
    	 */
    	public static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode";
    
    
    	/**
    	 * The name of the {@link AdviceMode} attribute for the annotation specified by the
    	 * generic type {@code A}. The default is {@value #DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME},
    	 * but subclasses may override in order to customize.
    	 */
    	protected String getAdviceModeAttributeName() {
    		return DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME;
    	}
    
    	/**
    	 * This implementation resolves the type of annotation from generic metadata and
    	 * validates that (a) the annotation is in fact present on the importing
    	 * {@code @Configuration} class and (b) that the given annotation has an
    	 * {@linkplain #getAdviceModeAttributeName() advice mode attribute} of type
    	 * {@link AdviceMode}.
    	 * 

    The {@link #selectImports(AdviceMode)} method is then invoked, allowing the * concrete implementation to choose imports in a safe and convenient fashion. * @throws IllegalArgumentException if expected annotation {@code A} is not present * on the importing {@code @Configuration} class or if {@link #selectImports(AdviceMode)} * returns {@code null} */ @Override public final String[] selectImports(AnnotationMetadata importingClassMetadata) { Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class); Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector"); AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType); if (attributes == null) { throw new IllegalArgumentException(String.format( "@%s is not present on importing class '%s' as expected", annType.getSimpleName(), importingClassMetadata.getClassName())); } AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName()); String[] imports = selectImports(adviceMode); if (imports == null) { throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode); } return imports; } /** * Determine which classes should be imported based on the given {@code AdviceMode}. *

    Returning {@code null} from this method indicates that the {@code AdviceMode} * could not be handled or was unknown and that an {@code IllegalArgumentException} * should be thrown. * @param adviceMode the value of the {@linkplain #getAdviceModeAttributeName() * advice mode attribute} for the annotation specified via generics. * @return array containing classes to import (empty array if none; * {@code null} if the given {@code AdviceMode} is unknown) */ @Nullable protected abstract String[] selectImports(AdviceMode adviceMode); }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    selectImports(AnnotationMetadata importingClassMetadata)是主要函数,实现了ImportSelector interface的主要逻辑,子类主要实现selectImports(AdviceMode adviceMode)添加自己的额外配置
    1, 获取子类具体的annotationType。Class annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);

    getClass: AsyncConfigurationSelector
    annType:EnableAsync

    ProxyAsyncConfiguration

    @Configuration(proxyBeanMethods = false)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
    
    	@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;
    	}
    
    }
    
    
    @Configuration(proxyBeanMethods = false)
    public abstract class AbstractAsyncConfiguration implements ImportAware {
    
    	@Nullable
    	protected AnnotationAttributes enableAsync;
    
    	@Nullable
    	protected Supplier<Executor> executor;
    
    	@Nullable
    	protected Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;
    
    
    	@Override
    	public void setImportMetadata(AnnotationMetadata importMetadata) {
    		this.enableAsync = AnnotationAttributes.fromMap(
    				importMetadata.getAnnotationAttributes(EnableAsync.class.getName()));
    		if (this.enableAsync == null) {
    			throw new IllegalArgumentException(
    					"@EnableAsync is not present on importing class " + importMetadata.getClassName());
    		}
    	}
    
    	/**
    	 * Collect any {@link AsyncConfigurer} beans through autowiring.
    	 */
    	@Autowired
    	void setConfigurers(ObjectProvider<AsyncConfigurer> configurers) {
    		Supplier<AsyncConfigurer> configurer = SingletonSupplier.of(() -> {
    			List<AsyncConfigurer> candidates = configurers.stream().collect(Collectors.toList());
    			if (CollectionUtils.isEmpty(candidates)) {
    				return null;
    			}
    			if (candidates.size() > 1) {
    				throw new IllegalStateException("Only one AsyncConfigurer may exist");
    			}
    			return candidates.get(0);
    		});
    		this.executor = adapt(configurer, AsyncConfigurer::getAsyncExecutor);
    		this.exceptionHandler = adapt(configurer, AsyncConfigurer::getAsyncUncaughtExceptionHandler);
    	}
    
    	private <T> Supplier<T> adapt(Supplier<AsyncConfigurer> supplier, Function<AsyncConfigurer, T> provider) {
    		return () -> {
    			AsyncConfigurer configurer = supplier.get();
    			return (configurer != null ? provider.apply(configurer) : null);
    		};
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    就是实例化一个AsyncAnnotationBeanPostProcessor并且设置配置值

    AsyncAnnotationAdvisor

    	protected Advice buildAdvice(
    			@Nullable Supplier<Executor> executor, @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
    
    		AnnotationAsyncExecutionInterceptor interceptor = new AnnotationAsyncExecutionInterceptor(null);
    		interceptor.configure(executor, exceptionHandler);
    		return interceptor;
    	}
    
    	/**
    	 * Calculate a pointcut for the given async annotation types, if any.
    	 * @param asyncAnnotationTypes the async annotation types to introspect
    	 * @return the applicable Pointcut object, or {@code null} if none
    	 */
    	protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
    		ComposablePointcut result = null;
    		for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
    			Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
    			Pointcut mpc = new AnnotationMatchingPointcut(null, asyncAnnotationType, true);
    			if (result == null) {
    				result = new ComposablePointcut(cpc);
    			}
    			else {
    				result.union(cpc);
    			}
    			result = result.union(mpc);
    		}
    		return (result != null ? result : Pointcut.TRUE);
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    主要就是advice和Pointcut 满足了PointcutAdvisor和Advisor接口,那么advisor又是在哪被调用的呢?在AsyncAnnotationBeanPostProcessor的继承树里面

    org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor#postProcessAfterInitialization

    	@Override
    	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);
    
    			// Use original ClassLoader if bean class not locally loaded in overriding class loader
    			ClassLoader classLoader = getProxyClassLoader();
    			if (classLoader instanceof SmartClassLoader && classLoader != bean.getClass().getClassLoader()) {
    				classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
    			}
    			return proxyFactory.getProxy(classLoader);
    		}
    
    		// No proxy needed.
    		return bean;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    那么pointCut又是什么时候用到的呢?根据常理,pointCut会决定这个bean是否需被proxy。

    在org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor#isEligible(java.lang.Class)

    	protected boolean isEligible(Class<?> targetClass) {
    		Boolean eligible = this.eligibleBeans.get(targetClass);
    		if (eligible != null) {
    			return eligible;
    		}
    		if (this.advisor == null) {
    			return false;
    		}
    		eligible = AopUtils.canApply(this.advisor, targetClass);
    		this.eligibleBeans.put(targetClass, eligible);
    		return eligible;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Advisor, java.lang.Class, boolean)

    	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
    		if (advisor instanceof IntroductionAdvisor) {
    			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
    		}
    		else if (advisor instanceof PointcutAdvisor) {
    			PointcutAdvisor pca = (PointcutAdvisor) advisor;
    			return canApply(pca.getPointcut(), targetClass, hasIntroductions);
    		}
    		else {
    			// It doesn't have a pointcut so we assume it applies.
    			return true;
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以看到根据PointcutAdvisor来决定是否应该创建proxy。

    至此,advice和Pointcut 的作用就都分析到了。

    AnnotationAsyncExecutionInterceptor

    	@Override
    	@Nullable
    	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);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    比起AsyncExecutionInterceptor,他就提供了一个功能:根据Async的value获取特定的executor。

    AsyncExecutionInterceptor

    public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor, Ordered {
    
    	/**
    	 * Create a new instance with a default {@link AsyncUncaughtExceptionHandler}.
    	 * @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
    	 * or {@link java.util.concurrent.ExecutorService}) to delegate to;
    	 * as of 4.2.6, a local executor for this interceptor will be built otherwise
    	 */
    	public AsyncExecutionInterceptor(@Nullable Executor defaultExecutor) {
    		super(defaultExecutor);
    	}
    
    	/**
    	 * Create a new {@code AsyncExecutionInterceptor}.
    	 * @param defaultExecutor the {@link Executor} (typically a Spring {@link AsyncTaskExecutor}
    	 * or {@link java.util.concurrent.ExecutorService}) to delegate to;
    	 * as of 4.2.6, a local executor for this interceptor will be built otherwise
    	 * @param exceptionHandler the {@link AsyncUncaughtExceptionHandler} to use
    	 */
    	public AsyncExecutionInterceptor(@Nullable Executor defaultExecutor, AsyncUncaughtExceptionHandler exceptionHandler) {
    		super(defaultExecutor, exceptionHandler);
    	}
    
    
    	/**
    	 * Intercept the given method invocation, submit the actual calling of the method to
    	 * the correct task executor and return immediately to the caller.
    	 * @param invocation the method to intercept and make asynchronous
    	 * @return {@link Future} if the original method returns {@code Future}; {@code null}
    	 * otherwise.
    	 */
    	@Override
    	@Nullable
    	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());
    	}
    
    	/**
    	 * This implementation is a no-op for compatibility in Spring 3.1.2.
    	 * Subclasses may override to provide support for extracting qualifier information,
    	 * e.g. via an annotation on the given method.
    	 * @return always {@code null}
    	 * @since 3.1.2
    	 * @see #determineAsyncExecutor(Method)
    	 */
    	@Override
    	@Nullable
    	protected String getExecutorQualifier(Method method) {
    		return null;
    	}
    
    	/**
    	 * This implementation searches for a unique {@link org.springframework.core.task.TaskExecutor}
    	 * bean in the context, or for an {@link Executor} bean named "taskExecutor" otherwise.
    	 * If neither of the two is resolvable (e.g. if no {@code BeanFactory} was configured at all),
    	 * this implementation falls back to a newly created {@link SimpleAsyncTaskExecutor} instance
    	 * for local use if no default could be found.
    	 * @see #DEFAULT_TASK_EXECUTOR_BEAN_NAME
    	 */
    	@Override
    	@Nullable
    	protected Executor getDefaultExecutor(@Nullable BeanFactory beanFactory) {
    		Executor defaultExecutor = super.getDefaultExecutor(beanFactory);
    		return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());
    	}
    
    	@Override
    	public int getOrder() {
    		return Ordered.HIGHEST_PRECEDENCE;
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    1, 提供默认的SimpleAsyncTaskExecutor
    2,最高的优先级

    determineAsyncExecutor

    	@Nullable
    	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;
    	}
    
    	@Nullable
    	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. " +
    						"Continuing search for an Executor bean named 'taskExecutor'", 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. " +
    						"Continuing search for an Executor bean named 'taskExecutor'", 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;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    由此我们可以看出executor的顺序:
    1, findQualifiedExecutor,
    2,return beanFactory.getBean(TaskExecutor.class);
    3,return beanFactory.getBean(DEFAULT_TASK_EXECUTOR_BEAN_NAME, Executor.class);
    4,return (defaultExecutor != null ? defaultExecutor : new SimpleAsyncTaskExecutor());

    exceptionUncaughtHandler就比较简单, this.exceptionHandler = new SingletonSupplier<>(exceptionHandler, SimpleAsyncUncaughtExceptionHandler::new);
    没有配置就直接SimpleAsyncUncaughtExceptionHandler。

  • 相关阅读:
    strimzi实战之二:部署和消息功能初体验
    TF-IDF
    基于html+jquery开发的科学计算器(课程作业)
    运行的 akrun 会打印信息到控制台,如何取消打印 -- chatGPT
    编译原理--中间代码优化算法总结
    浅层神经网络和深层神经网络介绍
    【问题收集】slam中常见make问题错误 相关总结
    深入理解node的web stream模块
    LTSPICE使用教程:二极管钳位电路仿真
    A-Level经济例题解析及练习A monopoly’s revenue
  • 原文地址:https://blog.csdn.net/weixin_45594127/article/details/127599094