Spring : AsyncAnnotationAdvisor

概述

这是一个Advisor,用于激活使用了异步方法调用,所基于的信息是这些方法或者这些方法所在实现类/接口上所使用异步注解。至于是哪些异步注解,可以通过AsyncAnnotationAdvisor来指定,如果不指定,缺省是指Spring @Async或者EJB 3.1 javax.ejb.Asynchronous

通过AsyncAnnotationAdvisor可以指定异步方法调用的任务执行器Executer和异步执行异常处理器AsyncUncaughtExceptionHandler

告诉AsyncAnnotationAdvisor处理哪些异步注解,指定相应的任务执行器和异步执行异常处理器之后,AsyncAnnotationAdvisor会生成以下产物供使用者使用 :

  • Pointcut – 匹配任意一个指定的异步注解的切面
  • AnnotationAsyncExecutionInterceptor – 一个异步方法执行拦截器,用于被使用者包裹到符合条件的bean

AsyncAnnotationAdvisor的使用参考AsyncAnnotationBeanPostProcessor

源代码

源代码版本 : spring-context-5.1.5.RELEASE

package org.springframework.scheduling.annotation;

// 省略 import 行

/**
 * Advisor that activates asynchronous method execution through the @Async
 * annotation. This annotation can be used at the method and type level in
 * implementation classes as well as in service interfaces.
 *
 * This advisor detects the EJB 3.1 javax.ejb.Asynchronous
 * annotation as well, treating it exactly like Spring's own Async.
 * Furthermore, a custom async annotation type may get specified through the
 * #setAsyncAnnotationType "asyncAnnotationType" property.
 *
 * @author Juergen Hoeller
 * @since 3.0
 * @see Async
 * @see AnnotationAsyncExecutionInterceptor
 */
@SuppressWarnings("serial")
public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {

	private Advice advice;

	private Pointcut pointcut;


	/**
	 * Create a new AsyncAnnotationAdvisor for bean-style configuration.
	 */
	public AsyncAnnotationAdvisor() {
		this((Supplier<Executor>) null, (Supplier<AsyncUncaughtExceptionHandler>) null);
	}

	/**
	 * Create a new AsyncAnnotationAdvisor for the given task executor.
	 * @param executor the task executor to use for asynchronous methods
	 * (can be null to trigger default executor resolution)
	 * @param exceptionHandler the AsyncUncaughtExceptionHandler to use to
	 * handle unexpected exception thrown by asynchronous method executions
	 * @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
	 */
	@SuppressWarnings("unchecked")
	public AsyncAnnotationAdvisor(
			@Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {

		this(SingletonSupplier.ofNullable(executor), SingletonSupplier.ofNullable(exceptionHandler));
	}

	/**
	 * Create a new AsyncAnnotationAdvisor for the given task executor.
	 * @param executor the task executor to use for asynchronous methods
	 * (can be null to trigger default executor resolution)
	 * @param exceptionHandler the AsyncUncaughtExceptionHandler to use to
	 * handle unexpected exception thrown by asynchronous method executions
	 * @since 5.1
	 * @see AnnotationAsyncExecutionInterceptor#getDefaultExecutor(BeanFactory)
	 */
	@SuppressWarnings("unchecked")
	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);
	}


	/**
	 *  设置所要解析的异步注解,如果不指定,使用缺省值 : @Async 和 EJB 3.1 javax.ejb.Asynchronous 
	 * 都支持
     * Set the 'async' annotation type.
	 * <p>The default async annotation type is the @Async annotation, as well
	 * as the EJB 3.1 javax.ejb.Asynchronous annotation (if present).
	 * This setter property exists so that developers can provide their own
	 * (non-Spring-specific) annotation type to indicate that a method is to
	 * be executed asynchronously.
	 * @param asyncAnnotationType the desired annotation type
	 */
	public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
		Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
		Set<Class<? extends Annotation>> asyncAnnotationTypes = new HashSet<>();
		asyncAnnotationTypes.add(asyncAnnotationType);
		this.pointcut = buildPointcut(asyncAnnotationTypes);
	}

	/**
	 * Set the {@code BeanFactory} to be used when looking up executors by qualifier.
	 */
	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		if (this.advice instanceof BeanFactoryAware) {
			((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
		}
	}


	@Override
	public Advice getAdvice() {
		return this.advice;
	}

	@Override
	public Pointcut getPointcut() {
		return this.pointcut;
	}


    // 构建 Advice, 实现类使用 AnnotationAsyncExecutionInterceptor,
    // 关联了指定的执行器 executor,和异步异常处理器 exceptionHandler
	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 null if none
	 */
	protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
		ComposablePointcut result = null;
      //   将 asyncAnnotationTypes 中所指定的注解联合构造一个组合切面对象 ComposablePointcut
      // 如果 asyncAnnotationTypes 则返回 Pointcut.TRUE, 表示比较时总是返回匹配
		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);
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值