Spring AOP-6 @Async生成AOP对象

一. 介绍

前面我们在介绍 Spring AOP 的时候生成 proxy 代理对象都是通过 AnnotationAwareAspectJAutoProxyCreator,以及它的抽象父类 AbstractAutoProxyCreator#postProcessAfterInitialization();

AbstractAutoProxyCreator 是一个 BeanPostProcessor,它的 postProcessAfterInitialization() 会找到 bean 容器中匹配的 advisors,如果有对应的 advisors 就会生成 AOP Proxy 代理对象;

但是我们发现 @Async 注解相关的 advisor 在 bean 容器中获取不到!它显然不是通过 AbstractAutoProxyCreator 这个 BeanPostProcessor 生成的 Proxy 代理类对象的;那它是怎么生成 proxy 代理对象的呢?它有 advisor 吗?

先说结论:

  1. @Async 注解相关的 advisor 不会放到 bean 容器里;
  2. @Async 注解相关的 advisor 会直接和 AsyncAnnotationBeanPostProcessor 创建绑定,@Async 注解相关的 proxy 是通过 AsyncAnnotationBeanPostProcessor#postProcessAfterInitialization() 生成的;

二. @Async配置

要使用 @Async 注解,需要在配置类上加上 @EnableAsync,因为 @EnableAsync 才会往容器中注入我们需要的 AsyncAnnotationBeanPostProcessor;

我们简单看下 @EnableAsync 开启的配置类;

// ------------------------------- AsyncConfigurationSelector -------------------------------
public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {

    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
        "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";


    /**
    */
    @Override
    @NonNull
    public String[] selectImports(AdviceMode adviceMode) {
        return switch (adviceMode) {
            // 默认往容器中注入 ProxyAsyncConfiguration 配置类,它是 JDK 代理相关的配置类
            // 如果是 Aspectj,导入的是 AspectJAsyncConfiguration 配置类
            case PROXY -> new String[] {ProxyAsyncConfiguration.class.getName()};
            case ASPECTJ -> new String[] {ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME};
        };
    }

}



// --------------------------------- 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() {
        // 1. 创建出 AsyncAnnotationBeanPostProcessor 并放到 bean 容器中
        AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
        
        // 2. 配置 @Async 相关的线程池 executor、错误处理器 exceptionHandler
        bpp.configure(this.executor, this.exceptionHandler);
        Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
        
        bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
        
        // 3. 设置 order,了解即可
        // @EnableAsync 默认的 order 是最小的,order = Ordered.LOWEST_PRECEDENCE
        // 之所以设置最小,是为了让 AsyncAnnotationBeanPostProcessor 在最后执行
        // 目的是让其他 BeanPostProcessor 执行完后,以便往现有代理中添加 advisor
        bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
        return bpp;
    }

}

我们来先看一下 AsyncAnnotationBeanPostProcessor 的类图,可以看到它是 BeanPostProssor 的实现类;

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

// -------------------------------- AsyncAnnotationBeanPostProcessor ------------------------------
public class AsyncAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor {

    public static final String DEFAULT_TASK_EXECUTOR_BEAN_NAME =
        AnnotationAsyncExecutionInterceptor.DEFAULT_TASK_EXECUTOR_BEAN_NAME;


    protected final Log logger = LogFactory.getLog(getClass());

    @Nullable
    private Supplier<Executor> executor;

    @Nullable
    private Supplier<AsyncUncaughtExceptionHandler> exceptionHandler;

    @Nullable
    private Class<? extends Annotation> asyncAnnotationType;



    public AsyncAnnotationBeanPostProcessor() {
        setBeforeExistingAdvisors(true);
    }


    public void configure(
        @Nullable Supplier<Executor> executor, 
        @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {

        this.executor = executor;
        this.exceptionHandler = exceptionHandler;
    }

    public void setExecutor(Executor executor) {
        this.executor = SingletonSupplier.of(executor);
    }

    public void setExceptionHandler(AsyncUncaughtExceptionHandler exceptionHandler) {
        this.exceptionHandler = SingletonSupplier.of(exceptionHandler);
    }

    public void setAsyncAnnotationType(Class<? extends Annotation> asyncAnnotationType) {
        Assert.notNull(asyncAnnotationType, "'asyncAnnotationType' must not be null");
        this.asyncAnnotationType = asyncAnnotationType;
    }


    /**
    * BeanFactoryAware 的接口,Spring Bean 容器初始化后会执行该后处理器
    *
    */
    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
        super.setBeanFactory(beanFactory);

        // 创建了一个 AsyncAnnotationAdvisor
        // 可以看到 @Async 相关的 advisor 不会放到 bean 容器中!
        // 而是直接和 AsyncAnnotationBeanPostProcessor 关联,且只有这一个 advisor
        // AsyncAnnotationAdvisor 的 pointcut 其实就是匹配类/方法上的 @Async 注解
        AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor,
                                                                    this.exceptionHandler);
        if (this.asyncAnnotationType != null) {
            advisor.setAsyncAnnotationType(this.asyncAnnotationType);
        }
        advisor.setBeanFactory(beanFactory);
        this.advisor = advisor;
    }

}

下面我们看下 AsyncAnnotationBeanPostProcessor 的 postProcessAfterInitialization() 做了啥;

三. AsyncAnnotationBeanPostProcessor

我们看下 AsyncAnnotationBeanPostProcessor 的 postProcessAfterInitialization();

public Object postProcessAfterInitialization(Object bean, String beanName) {
    // 1. advsior 是 AsyncAnnotationAdvisor,一般不会走进这个判断
    if (this.advisor == null || bean instanceof AopInfrastructureBean) {
        return bean;
    }

    // 2. 如果 bean 是 Advised 接口,表示 bean 已经是 Spring AOP 代理类对象
    // 这个我们在前面讲过,不记得的话可以看前面的章节
    if (bean instanceof Advised advised) {
        
        // 如果当前代理允许继续添加 advice 并且 当前 bean 需要代理的话
        if (!advised.isFrozen() && isEligible(AopUtils.getTargetClass(bean))) {
            
            // 默认就是 this.beforeExistingAdvisors == true
            // 表示将当前 AsyncAnnotationAdvisor 放在 advisor 的最前面,优先匹配 AsyncAnnotationAdvisor
            // 我们在上面讲过 AsyncAnnotationBeanPostProcessor 的 order 默认是最小的
            // 就是为了让所有的 advisors 加载完毕,好让 AsyncAnnotationAdvisor 放在第一位优先匹配!
            if (this.beforeExistingAdvisors) {
                advised.addAdvisor(0, this.advisor);
            }
            else if (advised.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE &&
                     advised.getAdvisorCount() > 0) {
                advised.addAdvisor(advised.getAdvisorCount() - 1, this.advisor);
                return bean;
            }
            else {
                advised.addAdvisor(this.advisor);
            }
            return bean;
        }
    }

    // 3. 当前 bean 不是 Advised 接口,表示 bean 还未被代理过,不是 Spring AOP 代理对象
    // 如果当前 bean 匹配 advisor 的话
    // 由我们去创建 ProxyFactory,放入 asyncAnnotationAdvisor,创建出 Proxy 代理类对象
    if (isEligible(bean, beanName)) {
        ProxyFactory proxyFactory = prepareProxyFactory(bean, beanName);
        if (!proxyFactory.isProxyTargetClass()) {
            evaluateProxyInterfaces(bean.getClass(), proxyFactory);
        }
        proxyFactory.addAdvisor(this.advisor);
        customizeProxyFactory(proxyFactory);

        ClassLoader classLoader = getProxyClassLoader();
        if (classLoader instanceof SmartClassLoader smartClassLoader &&
            classLoader != bean.getClass().getClassLoader()) {
            classLoader = smartClassLoader.getOriginalClassLoader();
        }
        return proxyFactory.getProxy(classLoader);
    }

    // 4. 不匹配当前 asyncAnnotationAdvisor,不进行代理,返回原始 bean 对象
    return bean;
}

至此,@Async 相关的 AsyncAnnotationAdvisor 就加入到了 ProxyFactory 的 advisors 里了,且生成了 Spring AOP 代理类对象;

下面我们看下 AsyncAnnotationAdvisor 中的 advice 是哪个?这个 Advice 的 invoke() 会对方法做哪些拦截改造呢?

四. AsyncAnnotationAdvisor

AsyncAnnotationAdvisor 类如下:

public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements BeanFactoryAware {

    // 对应的 advice
    private final Advice advice;

    // 对应的 pointcut
    private Pointcut pointcut;

    public AsyncAnnotationAdvisor() {
        this((Supplier<Executor>) null, (Supplier<AsyncUncaughtExceptionHandler>) null);
    }

    public AsyncAnnotationAdvisor(
        @Nullable Executor executor, @Nullable AsyncUncaughtExceptionHandler exceptionHandler) {
        this(SingletonSupplier.ofNullable(executor), SingletonSupplier.ofNullable(exceptionHandler));
    }

    @SuppressWarnings("unchecked")
    public AsyncAnnotationAdvisor(
        @Nullable Supplier<Executor> executor, 
        @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {
        
        Set<Class<? extends Annotation>> asyncAnnotationTypes = new LinkedHashSet<>(2);
        asyncAnnotationTypes.add(Async.class);

        ClassLoader classLoader = AsyncAnnotationAdvisor.class.getClassLoader();
        asyncAnnotationTypes.add((Class<? extends Annotation>)
                       ClassUtils.forName("jakarta.ejb.Asynchronous", classLoader));
        asyncAnnotationTypes.add((Class<? extends Annotation>)
                       ClassUtils.forName("jakarta.enterprise.concurrent.Asynchronous", classLoader));
       
        // 根据给定的 executor、exceptionHandler 创建出 Advice
        // 这个 Advice 根据下面可以看出是 AnnotationAsyncExecutionInterceptor
        this.advice = buildAdvice(executor, exceptionHandler);
        this.pointcut = buildPointcut(asyncAnnotationTypes);
    }


    protected Advice buildAdvice(
        @Nullable Supplier<Executor> executor, 
        @Nullable Supplier<AsyncUncaughtExceptionHandler> exceptionHandler) {

        // Advice 为 AnnotationAsyncExecutionInterceptor
        AnnotationAsyncExecutionInterceptor interceptor = 
            new AnnotationAsyncExecutionInterceptor(null);
        interceptor.configure(executor, exceptionHandler);
        return interceptor;
    }

    
    protected Pointcut buildPointcut(Set<Class<? extends Annotation>> asyncAnnotationTypes) {
        ComposablePointcut result = null;
        for (Class<? extends Annotation> asyncAnnotationType : asyncAnnotationTypes) {
            // class pointcut:匹配类上的 @Async 注解
            Pointcut cpc = new AnnotationMatchingPointcut(asyncAnnotationType, true);
            
            // method pointcut:匹配 method 上的 @Async 注解
            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);
    }

}

Advice 是 AnnotationAsyncExecutionInterceptor,我们看下 AnnotationAsyncExecutionInterceptor#invoke();它的 invoke() 在它的父类 AsyncExecutionInterceptor 上;

1. AnnotationAsyncExecutionInterceptor

AsyncExecutionInterceptor#invoke() 如下:

// ------------------------------- AsyncExecutionInterceptor ------------------------------
public Object invoke(final MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? 
                            AopUtils.getTargetClass(invocation.getThis()) : null);
    Method userMethod = BridgeMethodResolver.getMostSpecificMethod(invocation.getMethod(), 
                                                                   targetClass);
	
    // 1. 选择指定的线程池 asyncTaskExecutor
    AsyncTaskExecutor executor = determineAsyncExecutor(userMethod);

    // 2. 将目标方法的执行封装为一个 Callable 对象
    Callable<Object> task = () -> {
        try {
            Object result = invocation.proceed();
            if (result instanceof Future<?> future) {
                // 对于 @Async 注解的方法
                // 如果方法需要返回值,需要包装成 Future 类对象
                // 一般是 AsyncResult,如 return new AsyncResult<>("ok")
                return future.get();
            }
        }
        catch (ExecutionException ex) {
            handleError(ex.getCause(), userMethod, invocation.getArguments());
        }
        catch (Throwable ex) {
            // 3. 如果有异常的话,进行异常处理
            handleError(ex, userMethod, invocation.getArguments());
        }
        return null;
    };

    // 4. 执行 doSubmit()
    // 将封装好的 task 提交到线程池 asyncTaskExecutor 中执行
    return doSubmit(task, executor, invocation.getMethod().getReturnType());
}



// ------------------------------- AsyncExecutionInterceptor ------------------------------
protected Object doSubmit(Callable<Object> task, AsyncTaskExecutor executor, Class<?> returnType) {
    
    // 1. 方法返回值是 ListenableFuture、Future 之类时,会返回 Future 类对象
    if (CompletableFuture.class.isAssignableFrom(returnType)) {
        return executor.submitCompletable(task);
    }
    else if (ListenableFuture.class.isAssignableFrom(returnType)) {
        return ((org.springframework.core.task.AsyncListenableTaskExecutor)executor)
            .submitListenable(task);
    }
    else if (Future.class.isAssignableFrom(returnType)) {
        return executor.submit(task);
    }
    
    // 2. 方法返回值是 void,返回 null
    else if (void.class == returnType) {
        executor.submit(task);
        return null;
    }
    
    // 3. 方法返回值只能是 Future、void,其他类型会抛异常
    else {
        throw new IllegalArgumentException(
            "Invalid return type for async method (only Future and void supported): " + returnType);
    }
}

至此,AsyncExecutionInterceptor#invoke() 结束;

  • 18
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值