spring會根據定義的AdviceMode類型(PROXY, ASPECTJ)選擇不一樣的aop實現方式, 通常使用的是PROXY 。java
SpringBoot當要使用@Async時,需啓動類顯示聲明@EnableAsync 來 注入 AsyncConfigurationSelector(AdviceModeImportSelector的擴展實現);spring
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> { private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"; /** * @return {@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 org.springframework.context.annotation.AdviceMode.PROXY: return new String[] { ProxyAsyncConfiguration.class.getName() }; case org.springframework.context.annotation.AdviceMode.ASPECTJ: return new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME }; default: return null; } } }
默認是AdviceMode.PROXY, 因此選擇ProxyAsyncConfiguration, 初始化AsyncAnnotationBeanPostProcessor,含成員變量Advisor。c#
// AbstractAsyncConfiguration @Override 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()); } } // 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(); Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation"); if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) { bpp.setAsyncAnnotationType(customAsyncAnnotation); } if (this.executor != null) { bpp.setExecutor(this.executor); } if (this.exceptionHandler != null) { bpp.setExceptionHandler(this.exceptionHandler); } bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass")); bpp.setOrder(this.enableAsync.<Integer>getNumber("order")); return bpp; }
AsyncAnnotationBeanPostProcessor 繼承了 BeanFactoryAware 接口。在setBeanFactory方法中,初始化了AsyncAnnotationAdvisor !這就比較熟悉了。異步
@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; }
PS:@EnableAsync 能夠經過設置屬性 annotation 來指定自定義註解類型 。async
ProxyAsyncConfiguration構建AsyncAnnotationBeanPostProcessor時這個參數值被注入到其內部屬性AsyncAnnotationType,並在 setBeanFactory 方法中被注入進AsyncAnnotationAdvisoride
在具體的構造函數中 綁定了advice (AnnotationAsyncExecutionInterceptor )與pointcut(ComposablePointcut), 並指定切面註解類型是@Async函數
(在自定義advisor 時, advice與 pointcut 是advisor內共享成員變量)post
extends AsyncExecutionInterceptor extends AsyncExecutionAspectSupport implements MethodInterceptor。ui
由MethodInterceptor的定義可見: MethodInterceptor就是所謂的Advicethis
public interface Interceptor extends Advice {} public interface MethodInterceptor extends Interceptor { /** * Implement this method to perform extra treatments before and * after the invocation. Polite implementations would certainly * like to invoke {@link Joinpoint#proceed()}. * @param invocation the method invocation joinpoint * @return the result of the call to {@link Joinpoint#proceed()}; * might be intercepted by the interceptor * @throws Throwable if the interceptors or the target object * throws an exception */ Object invoke(MethodInvocation invocation) throws Throwable; }
AsyncExecutionAspectSupport.invoke 就是指定切面在命中時具體處理邏輯。
比較重要的是如何選擇異步處理的線程池AsyncTaskExecutor的過程 determineAsyncExecutor方法:
優先獲取方法或方法所在類 配置的@Async指定的異步處理線程池對象名,在beanFactory中匹配線程次實例。
其次則是在初始化AnnotationAsyncExecutionInterceptor時從BeanFactory獲取的 TaskExecutor.class類型對象。
單個pointcut由MethodMatcher (方法匹配)與 ClassFilter (類匹配)組合構成。
public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher(); /** * Canonical Pointcut instance that always matches. */ Pointcut TRUE = TruePointcut.INSTANCE; }
經常使用的有
如下是spring針對Async構建的ComposablePointcut ,是由2個AnnotationMatchingPointcut 取並集而成。這也佐證了對於類及方法上的@Async都有效
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); }
那是何時執行條件過濾呢?
回到AsyncAnnotationBeanPostProcessor,不單單繼承BeanFactoryAware, 並且還實現了BeanPostProcessor接口!
在執行postProcessAfterInitialization方法內, 經過isEligible 方法對bean進行斷定是否須要代理:會優先經過Pointcut的ClassFilter進行斷定, 其次是MethodMatcher!
最終也是經過AopProxy.getProxy() 構建代理對象。AopProxy由ProxyCreatorSupport的createAopProxy()方法提供實例
p