如何通过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
相关产品推荐
相关产品推荐

