You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过ProxyFactory使@Async生效?正确实现方式探讨

解决方案:规范获取AsyncAdvisor并复用代理对象

一、原有写法的问题

直接new AsyncAnnotationAdvisor()的方式虽能让@Async生效,但不符合Spring最佳实践:

  • 无法复用容器中自定义的TaskExecutor或AsyncUncaughtExceptionHandler配置,默认只会使用Spring内置的简易线程池
  • 每次创建代理都新建Advisor实例,造成资源浪费,也无法保证异步行为的一致性

二、规范获取AsyncAdvisor的方式

将AsyncAnnotationAdvisor定义为Spring单例Bean,让它自动关联容器中的异步配置:

@Configuration
@EnableAsync
public class AsyncConfig {

    @Bean
    public AsyncAnnotationAdvisor asyncAnnotationAdvisor(
            @Autowired(required = false) TaskExecutor taskExecutor,
            @Autowired(required = false) AsyncUncaughtExceptionHandler exceptionHandler) {
        // 传入容器中的自定义线程池和异常处理器,无自定义则用Spring默认实现
        return new AsyncAnnotationAdvisor(taskExecutor, exceptionHandler);
    }
}

三、复用Advisor与代理对象的最佳实践

不在每次调用时创建代理,而是在初始化Actor映射时一次性创建代理并存入Map,同时复用同一个Advisor实例:

@Component
public class ActorManager {

    private final Map<String, Actor> actorMap = new ConcurrentHashMap<>();
    private final AsyncAnnotationAdvisor asyncAnnotationAdvisor;

    // 注入容器中的单例AsyncAnnotationAdvisor
    public ActorManager(AsyncAnnotationAdvisor asyncAnnotationAdvisor) {
        this.asyncAnnotationAdvisor = asyncAnnotationAdvisor;
        initActorMap();
    }

    private void initActorMap() {
        // 假设从数据库/配置/容器中获取所有真实Actor实例
        Collection<Actor> realActors = fetchRealActorInstances();
        for (Actor realActor : realActors) {
            Actor proxyActor = createAsyncProxy(realActor);
            actorMap.put(getActorKey(realActor), proxyActor);
        }
    }

    private Actor createAsyncProxy(Actor target) {
        ProxyFactory proxyFactory = new ProxyFactory(target);
        proxyFactory.addInterface(Actor.class);
        // 复用全局的AsyncAnnotationAdvisor
        proxyFactory.addAdvisor(asyncAnnotationAdvisor);
        // 基于接口生成JDK动态代理
        proxyFactory.setProxyTargetClass(false);
        return (Actor) proxyFactory.getProxy();
    }

    // 对外提供获取代理Actor的方法
    public Actor getActor(String actorName) {
        return actorMap.get(actorName);
    }
}

四、调用方式

之后直接从映射中取代理对象调用,@Async会稳定生效:

Actor actor = actorManager.getActor("actorName");
actor.doAction(...);

内容的提问来源于stack exchange,提问作者loshad vtapkah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:45:30