@Async和@EnableAsync注解解析

1,@Async注解

Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
Can also be used at the type level, in which case all of the type's methods are
considered as asynchronous.
这个注解标志着某个方法作作为异步执行候选者。这个注解可以加在类的层级上,表示该类的所有方法都被认
为是异步执行。

<p>In terms of target method signatures, any parameter types are supported.
However, the return type is constrained to either {@code void} or
{@link java.util.concurrent.Future}. In the latter case, you may declare the
more specific {@link org.springframework.util.concurrent.ListenableFuture} or
{@link java.util.concurrent.CompletableFuture} types which allow for richer
interaction with the asynchronous task and for immediate composition with
further processing steps.
在目标的方法签名方面,任何的方法参数类型都是支持的,返回类型只能是void或者Future类,使用后一种
返回类型时你可以特别的声明返回ListenableFuture或者CompleteFuture类型,这两种返回类型允许更丰富
地与异步任务进行交互以及组装返回值用于下一步的处理。

<p>A {@code Future} handle returned from the proxy will be an actual asynchronous
{@code Future} that can be used to track the result of the asynchronous method
execution. However, since the target method needs to implement the same signature,
it will have to return a temporary {@code Future} handle that just passes a value
through: e.g. Spring's {@link AsyncResult}, EJB 3.1's {@link javax.ejb.AsyncResult},
or {@link java.util.concurrent.CompletableFuture#completedFuture(Object)}.
从代理返回的{@code Future}句柄将是实际的异步{@code Future}可用于跟踪异步方法的结果执行。
然而,因为目标方法需要实现同样的方法签名,目标方法也需要返回一个仅传递值的临时的Future
句柄通过:例如spring的AsyncResult或javax.ejb.AsyncResult或java.util.concurrent.CompletableFuture
来传递。

 

2,@EnableAsync

Enables Spring's asynchronous method execution capability, similar to functionality
found in Spring's {@code <task:*>} XML namespace.
启用spring异步方法执行功能,该注解的功能和xml中<task:*>的命名空间功能相似

<p>To be used together with @{@link Configuration Configuration} classes as follows,
enabling annotation-driven async processing for an entire Spring application context:

按如下方式与@Configuration注解类同时使用,为整个springs application上下文启用注解驱动的异步处理
功能。

<pre class="code">
&#064;Configuration
&#064;EnableAsync
public class AppConfig {

}</pre>

{@code MyAsyncBean} is a user-defined type with one or more methods annotated with
either Spring's {@code @Async} annotation, the EJB 3.1 {@code @javax.ejb.Asynchronous}
annotation, or any custom annotation specified via the {@link #annotation} attribute.
The aspect is added transparently for any registered bean, for instance via this
configuration:

MyAsyncBean是一个用户定义的类,类中含一个或一个以上@Async注解 或@Asynchronouss注解或任何通过
anntation attribute指定的自定义注解,切面是显式添加到任何已经注册到spring容器的bean上的,
举例,通过这个配置:

<pre class="code">
&#064;Configuration
public class AnotherAppConfig {

&#064;Bean
public MyAsyncBean asyncBean() {
return new MyAsyncBean();
}
}</pre>

<p>By default, Spring will be searching for an associated thread pool definition:
either a unique {@link org.springframework.core.task.TaskExecutor} bean in the context,
or an {@link java.util.concurrent.Executor} bean named "taskExecutor" otherwise. If
neither of the two is resolvable, a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
will be used to process async method invocations. Besides, annotated methods having a
{@code void} return type cannot transmit any exception back to the caller. By default,
such uncaught exceptions are only logged.
默认情况下,spring会搜索如下定义的关联线程池,要么是一个在spring context中唯一的TaskExecutor实现bean,
要么是一个beanname为"taskExecutor"的Executor实现bean,如果以上两个实例都没有找到,那么SimpAsyncTaskExcutor会被用来处理异步方法调用。此外,异步注解的方法如果返回类型是void,那么该方法不能将异步方法执行产生的异常信息传递到异步方法的调用方默认情况下,这些未捕获的异常只能在日志中记录。

 

<p>To customize all this, implement {@link AsyncConfigurer} and provide:
<ul>
<li>your own {@link java.util.concurrent.Executor Executor} through the
{@link AsyncConfigurer#getAsyncExecutor getAsyncExecutor()} method, and</li>
<li>your own {@link org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
AsyncUncaughtExceptionHandler} through the {@link AsyncConfigurer#getAsyncUncaughtExceptionHandler
getAsyncUncaughtExceptionHandler()}
method.</li>
</ul>
定制所有这些,需要实现AsyncConfigurer接口,和通过AsyncConfigurer#getAsyncExecutor方法提供Exector的
实现类,通过AsyncConfigurer#getAsyncUncaughtExceptionHandler方法提供AsyncUncaughtExceptionHandler接口
的实现类

<p><b>NOTE: {@link AsyncConfigurer} configuration classes get initialized early
in the application context bootstrap. If you need any dependencies on other beans
there, make sure to declare them 'lazy' as far as possible in order to let them
go through other post-processors as well.</b>

<pre class="code">
&#064;Configuration
&#064;EnableAsync
public class AppConfig implements AsyncConfigurer {

&#064;Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(7);
executor.setMaxPoolSize(42);
executor.setQueueCapacity(11);
executor.setThreadNamePrefix("MyExecutor-");
executor.initialize();
return executor;
}

&#064;Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new MyAsyncUncaughtExceptionHandler();
}
}</pre>

<p>If only one item needs to be customized, {@code null} can be returned to
keep the default settings. Consider also extending from {@link AsyncConfigurerSupport}
when possible.

如果只定制部分内容,那么以上方法可以返回null来保持默认配置。另外尽可能考虑继承AsyncConfigurerSupport类

<p>Note: In the above example the {@code ThreadPoolTaskExecutor} is not a fully managed
Spring bean. Add the {@code @Bean} annotation to the {@code getAsyncExecutor()} method
if you want a fully managed bean. In such circumstances it is no longer necessary to
manually call the {@code executor.initialize()} method as this will be invoked
automatically when the bean is initialized.

注意:在上面的例子中,ThreadPoolTaskExecutor类不是完全受spring管理的bean, 在getAsyncExecutor()
方法上添加@Bean注解可以让它完全受spring管理。在这种情况下executor.initialize()方法不需要手动调用,
因为initizalze()方法会在类初始化时被自动调用。

<p>For reference, the example above can be compared to the following Spring XML
configuration:

举例,以上的例子可以用xml配置形式进行如下的配置:

<pre class="code">
&lt;beans&gt;EnableAsync

&lt;task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/&gt;

&lt;task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/&gt;

&lt;bean id="asyncBean" class="com.foo.MyAsyncBean"/&gt;

&lt;bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/&gt;

&lt;/beans&gt;
</pre>

The above XML-based and JavaConfig-based examples are equivalent except for the
setting of the <em>thread name prefix</em> of the {@code Executor}; this is because
the {@code <task:executor>} element does not expose such an attribute. This
demonstrates how the JavaConfig-based approach allows for maximum configurability
through direct access to actual componentry.

以上xml的配置和java注解的配置基本上是相同的,除了Executor线程名字的前缀配置不同。
这是因为<task:executor>元素没有暴露这个配置项。这示范了使用java注解能最大化类的可配置性。

<p>The {@link #mode} attribute controls how advice is applied: If the mode is
{@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
of the proxying. 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.

EnableAsync注解类的属性mode,控制着切面是如何被应用的:如果mode是AdviceMode#PROXY(默认)
那么其他的属性控制着代理行为。注意代理模式只允许通过代理方式实现方法调用的拦截;这种方式
下同一个类中的本地方法调用不会被拦截。

<p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
this case the {@code spring-aspects} module JAR must be present on the classpath, with
compile-time weaving or load-time weaving applying the aspect to the affected classes.
There is no proxy involved in such a scenario; local calls will be intercepted as well.

注意如果mode被设置成AdviceMode#ASPECTJ,那么#proxyTargetClass属性会被忽略。同时注意在这种模式下
spring-aspects的jar包需要在项目的classpath下,在编译时或加载时将切面织入到影响的类。
这种方案下没有涉及代理;同一类的本地方法调用也可以被拦截。

 

下面看看在哪一步会将切面织入到影响的类中,在源码Async类的边上找到了AsyncAnnotationBeanPostProcessor这个类,解读类名可以看到这个类是执行Async注解类实例化后的处理操作的。

1,该类有一个setBeanFactory的方法,该方法新建了一个AsyncAnnotationAdvisor类,并将该类设置给成员变量advisor。

2,该类还有一个postProcessAfterInitialization()方法,在bean初始化后,为@Async注解的类生产代理对象,以及设置代理对象的拦截器(DynamicAdvisedInterceptor)。

Bean post-processor that automatically applies asynchronous invocation behavior to any bean that carries the {@link Async} annotation at  class or method-level by adding a corresponding {@link AsyncAnnotationAdvisor} to the
exposed proxy (either an existing AOP proxy or a newly generated proxy that implements all of the target's interfaces).
bean后置处理器自动在@Async注解的类或方法的代理上添加异步调用的行为

<p>The {@link TaskExecutor} responsible for the asynchronous execution may be provided as well as the annotation type that indicates a    method should be invoked asynchronously. If no annotation type is specified, this post-processor will detect both Spring's {@link Async @Async} annotation as well as the EJB 3.1 {@code javax.ejb.Asynchronous} annotation.
TaskExector负责异步方法的执行,taskExector和annotationType可能同时被提供,标识这个方法会被异步执行。如果annotation type没有被特殊指定,那么bean后置处理器会探测@Async注解和@Asynchronous注解


<p>For methods having a {@code void} return type, any exception thrown during the asynchronous method invocation cannot be accessed by the caller. An {@link AsyncUncaughtExceptionHandler} can be specified to handle these cases.

<p>Note: The underlying async advisor applies before existing advisors by default, in order to switch to async execution as early as      possible in the invocation chain.
注意: 默认情况下潜在的async advisor会优先于存在的advisors进行使用,为了尽可能在调用链的早期就切换成异步调用

 

 新建advisor类,并在AsyncAnnotationBeanPostProcessor属性中设置advisor通知类

//AsyncAnnotationBeanPostProcessor
@Override
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;
}

 

新建AsyncAnnotationAdvisor类,并设置advice通知,实际的通知类为AnnotationAsyncExecutionInterceptor类,设置pointcut切点

//AsyncAnnotationAdvisor
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);
}

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);
}

 

 AbstractAdvisingBeanPostProcessor类继承层次

 

 

AsyncAnnotationBeanPostProcessor执行postProcessAfterInitialization方法

//AsyncAnnotationBeanPostProcessor
@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);
		return proxyFactory.getProxy(getProxyClassLoader());
	}

	// No proxy needed.
	return bean;
}

  

 

//DefaultAopProxyFactory
/**
 * Create a new proxy according to the settings in this factory.
 * <p>Can be called repeatedly. Effect will vary if we've added
 * or removed interfaces. Can add and remove interceptors.
 * <p>Uses the given class loader (if necessary for proxy creation).
 * @param classLoader the class loader to create the proxy with
 * (or {@code null} for the low-level proxy facility's default)
 * @return the proxy object
 */
public Object getProxy(@Nullable ClassLoader classLoader) {
	return createAopProxy().getProxy(classLoader);
}

 

获得代理工厂并创建Cglib代理类

//ProxyCreatorSupport
/**
 * Subclasses should call this to get a new AOP proxy. They should <b>not</b>
 * create an AOP proxy with {@code this} as an argument.
 */
protected final synchronized AopProxy createAopProxy() {
	if (!this.active) {
		activate();
	}
	return getAopProxyFactory().createAopProxy(this);
}

  

创建AopProxy代理工厂,这里创建的代理工厂为ObjenesisCglibAopProxy

//DefaultAopProxyFactory, create a CGLIB proxy if one the following is true for a given instance.optimize is true,proxyTargetClass is true,
// no proxy interfaces have been specified @Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }

  

下面是创建代理类的核心逻辑,新建一个Enhancer(增强类),这个类是被代理类的一个子类enhaner.setSuperclass(proxySuperClass),创建代理类以及代理实例,并设置回调

//CglibAopProxy
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
	if (logger.isTraceEnabled()) {
		logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource());
	}

	try {
		Class<?> rootClass = this.advised.getTargetClass();
		Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

		Class<?> proxySuperClass = rootClass;
		if (ClassUtils.isCglibProxyClass(rootClass)) {
			proxySuperClass = rootClass.getSuperclass();
			Class<?>[] additionalInterfaces = rootClass.getInterfaces();
			for (Class<?> additionalInterface : additionalInterfaces) {
				this.advised.addInterface(additionalInterface);
			}
		}

		// Validate the class, writing log messages as necessary.
		validateClassIfNecessary(proxySuperClass, classLoader);

		// Configure CGLIB Enhancer...
		Enhancer enhancer = createEnhancer();
		if (classLoader != null) {
			enhancer.setClassLoader(classLoader);
			if (classLoader instanceof SmartClassLoader &&
					((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
				enhancer.setUseCache(false);
			}
		}
		enhancer.setSuperclass(proxySuperClass);
		enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
		enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
		enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

		Callback[] callbacks = getCallbacks(rootClass);
		Class<?>[] types = new Class<?>[callbacks.length];
		for (int x = 0; x < types.length; x++) {
			types[x] = callbacks[x].getClass();
		}
		// fixedInterceptorMap only populated at this point, after getCallbacks call above
		enhancer.setCallbackFilter(new ProxyCallbackFilter(
				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
		enhancer.setCallbackTypes(types);

		// Generate the proxy class and create a proxy instance.
		return createProxyClassAndInstance(enhancer, callbacks);
	}
	catch (CodeGenerationException | IllegalArgumentException ex) {
		..
	}
	catch (Throwable ex) {
		..
	}
}

 

 获得代理类的回调,DynamicAdvisedInterceptor是aop方法调用时使用的拦截器,也是代理方法调用时的入口类

//CglibAopProxy
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
	// Parameters used for optimization choices...
	boolean exposeProxy = this.advised.isExposeProxy();
	boolean isFrozen = this.advised.isFrozen();
	boolean isStatic = this.advised.getTargetSource().isStatic();

	// Choose an "aop" interceptor (used for AOP calls)aop方法调用时使用的拦截器,在也是代理方法调用时的入口类
	Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);

	// Choose a "straight to target" interceptor. (used for calls that are
	// unadvised but can return this). May be required to expose the proxy.
	Callback targetInterceptor;
	if (exposeProxy) {
		targetInterceptor = (isStatic ?
				new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
				new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
	}
	else {
		targetInterceptor = (isStatic ?
				new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
				new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
	}

	// Choose a "direct to target" dispatcher (used for
	// unadvised calls to static targets that cannot return this).
	Callback targetDispatcher = (isStatic ?
			new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());

	Callback[] mainCallbacks = new Callback[] {
			aopInterceptor,  // for normal advice
			targetInterceptor,  // invoke target without considering advice, if optimized
			new SerializableNoOp(),  // no override for methods mapped to this
			targetDispatcher, this.advisedDispatcher,
			new EqualsInterceptor(this.advised),
			new HashCodeInterceptor(this.advised)
	};

	Callback[] callbacks;

	// If the target is a static one and the advice chain is frozen,
	// then we can make some optimizations by sending the AOP calls
	// direct to the target using the fixed chain for that method.
	if (isStatic && isFrozen) {
		Method[] methods = rootClass.getMethods();
		Callback[] fixedCallbacks = new Callback[methods.length];
		this.fixedInterceptorMap = new HashMap<>(methods.length);

		// TODO: small memory optimization here (can skip creation for methods with no advice)
		for (int x = 0; x < methods.length; x++) {
			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
			fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
					chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
			this.fixedInterceptorMap.put(methods[x].toString(), x);
		}

		// Now copy both the callbacks from mainCallbacks
		// and fixedCallbacks into the callbacks array.
		callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
		System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
		System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
		this.fixedInterceptorOffset = mainCallbacks.length;
	}
	else {
		callbacks = mainCallbacks;
	}
	return callbacks;
}

  

创建代理类以及代理类的实例,并设置代理类的回调(setCallbacks)

//ObjenesisCglibAopProxy
@Override
@SuppressWarnings("unchecked")
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
	Class<?> proxyClass = enhancer.createClass();
	Object proxyInstance = null;

	if (objenesis.isWorthTrying()) {
		try {
			proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
		}
		catch (Throwable ex) {
			logger.debug("Unable to instantiate proxy using Objenesis, " +
					"falling back to regular proxy construction", ex);
		}
	}

	if (proxyInstance == null) {
		// Regular instantiation via default constructor...
		try {
			Constructor<?> ctor = (this.constructorArgs != null ?
					proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
					proxyClass.getDeclaredConstructor());
			ReflectionUtils.makeAccessible(ctor);
			proxyInstance = (this.constructorArgs != null ?
					ctor.newInstance(this.constructorArgs) : ctor.newInstance());
		}
		catch (Throwable ex) {
			throw new AopConfigException("Unable to instantiate proxy using Objenesis, " +
					"and regular proxy instantiation via default constructor fails as well", ex);
		}
	}

	((Factory) proxyInstance).setCallbacks(callbacks);
	return proxyInstance;
}

 

 @Ansync注解的方法被调用时会被DynamicAdvisedInterceptor拦截,先进入DynamicAdvisedInterceptor.intercept方法

//DynamicAdvisedInterceptor
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
	Object oldProxy = null;
	boolean setProxyContext = false;
	Object target = null;
	TargetSource targetSource = this.advised.getTargetSource();
	try {
		if (this.advised.exposeProxy) {
			// Make invocation available if necessary.
			oldProxy = AopContext.setCurrentProxy(proxy);
			setProxyContext = true;
		}
		// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
		target = targetSource.getTarget();
		Class<?> targetClass = (target != null ? target.getClass() : null);
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		Object retVal;
		// Check whether we only have one InvokerInterceptor: that is,
		// no real advice, but just reflective invocation of the target.
		if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
			// We can skip creating a MethodInvocation: just invoke the target directly.
			// Note that the final invoker must be an InvokerInterceptor, so we know
			// it does nothing but a reflective operation on the target, and no hot
			// swapping or fancy proxying.
			Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
			retVal = methodProxy.invoke(target, argsToUse);
		}
		else {
			// 实际使用的时Cglib方法代理 We need to create a method invocation...
			retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
		}
		retVal = processReturnType(proxy, target, method, retVal);
		return retVal;
	}
	finally {
		if (target != null && !targetSource.isStatic()) {
			targetSource.releaseTarget(target);
		}
		if (setProxyContext) {
			// Restore old proxy.
			AopContext.setCurrentProxy(oldProxy);
		}
	}
}

  

@Async注解方法被调用前,会先调用ReflectiveMethodInvocation.process()方法

//ReflectiveMethodInvocation
@Override
@Nullable
public Object proceed() throws Throwable {
	//	We start with an index of -1 and increment early.
	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
		return invokeJoinpoint();
	}

	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
		if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}

  

进入AsyncExecutionInterceptor拦截器,进行方法实际的增强

//AsyncExecutionInterceptor
/**
 * 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());
}

 

将实际的执行方法放到线程池中执行,并返回异步方法的Future结果或者null

/**
 * Delegate for actually executing the given task with the chosen executor.
 * @param task the task to execute
 * @param executor the chosen executor
 * @param returnType the declared return type (potentially a {@link Future} variant)
 * @return the execution result (potentially a corresponding {@link Future} handle)
 */
@Nullable
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
	if (CompletableFuture.class.isAssignableFrom(returnType)) {
		return CompletableFuture.supplyAsync(() -> {
			try {
				return task.call();
			}
			catch (Throwable ex) {
				throw new CompletionException(ex);
			}
		}, executor);
	}
	else 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;
	}
}

 

posted @ 2020-06-05 15:02  2412cyy  阅读(4549)  评论(0编辑  收藏  举报