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