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

高并发Spring应用中,如何强制使用CglibAopProxy$DynamicUnadvisedInterceptor优化性能?

最佳优化方案(无需覆盖Spring核心类)

针对你遇到的高并发Spring Web应用中代理带来的性能瓶颈,核心问题在于请求作用域Bean的默认代理会强制绑定一个Advisor,导致Spring使用DynamicAdvisedInterceptor而非更轻量的DynamicUnadvisedInterceptor,进而引发ConcurrentHashMap竞争和高CPU开销。以下是无需修改Spring核心类的可行方案:

方案一:自定义无通知的作用域代理FactoryBean

既然默认ScopedProxyFactoryBean会给代理添加ScopedObjectAdvisor,我们可以直接实现一个跳过Advisor绑定的自定义FactoryBean,让代理自动使用DynamicUnadvisedInterceptor:

实现步骤

  1. 编写自定义FactoryBean,继承ScopedProxyFactoryBean并重写代理创建逻辑:
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.scope.ScopedProxyFactoryBean;

public class NoAdviceScopedProxyFactoryBean extends ScopedProxyFactoryBean {
    @Override
    protected Object createProxy(ClassLoader classLoader, Object[] interfaces) {
        ProxyFactory proxyFactory = new ProxyFactory();
        // 保留作用域代理的核心目标源逻辑
        proxyFactory.setTargetSource(getTargetSource());
        // 保留接口配置(适配有接口的Bean)
        proxyFactory.setInterfaces(interfaces);
        // 强制使用CGLIB代理(适配无接口的Bean)
        proxyFactory.setProxyTargetClass(true);
        // 关键:不添加任何Advisor,让Spring自动使用无通知拦截器
        return proxyFactory.getProxy(classLoader);
    }
}
  1. 替换默认的作用域代理配置:
    • XML配置场景:替换<aop:scoped-proxy/>为自定义FactoryBean:
      <bean id="requestScopedBean" class="com.yourpackage.YourRequestScopedBean" scope="request">
          <property name="someProperty" value="someValue"/>
      </bean>
      <bean class="com.yourpackage.NoAdviceScopedProxyFactoryBean">
          <property name="targetBeanName" value="requestScopedBean"/>
      </bean>
      
    • 注解配置场景:通过自定义FactoryBean创建代理,关闭默认代理模式:
      @Bean
      public NoAdviceScopedProxyFactoryBean requestScopedBeanProxy() {
          NoAdviceScopedProxyFactoryBean factoryBean = new NoAdviceScopedProxyFactoryBean();
          factoryBean.setTargetBeanName("innerRequestScopedBean");
          return factoryBean;
      }
      
      @Bean
      @Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.NO)
      public YourRequestScopedBean innerRequestScopedBean() {
          return new YourRequestScopedBean();
      }
      

方案二:全局替换AopProxyFactory(适用于所有无通知代理场景)

如果你的应用中所有代理Bean都没有业务通知,可通过自定义AopProxyFactory全局控制代理使用的拦截器:

实现步骤

  1. 实现自定义AopProxyFactory,继承DefaultAopProxyFactory,针对无Advisor的场景返回轻量代理:
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.DefaultAopProxyFactory;
import org.springframework.aop.framework.aopalliance.AopProxy;

public class NoAdviceAopProxyFactory extends DefaultAopProxyFactory {
    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
        // 无Advisor且使用CGLIB代理时,返回自定义轻量代理
        if (config.getAdvisors().length == 0 && config.isProxyTargetClass()) {
            return new NoAdviceCglibAopProxy(config);
        }
        return super.createAopProxy(config);
    }
}
  1. 实现简化版无通知CGLIB代理(参考Spring原生CglibAopProxy逻辑,仅保留无通知拦截器):
import org.springframework.aop.framework.AdvisedSupport;
import org.springframework.aop.framework.CglibAopProxy;
import org.springframework.aop.framework.DynamicUnadvisedInterceptor;
import org.springframework.cglib.proxy.Callback;

public class NoAdviceCglibAopProxy extends CglibAopProxy {
    public NoAdviceCglibAopProxy(AdvisedSupport config) {
        super(config);
    }

    @Override
    protected Callback[] getCallbacks() {
        // 仅返回无通知拦截器,跳过所有通知逻辑
        return new Callback[]{
                new DynamicUnadvisedInterceptor(this.advised),
                new SerializableNoOp()
        };
    }
}
  1. 在Spring上下文初始化时替换默认工厂:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;

public class CustomApplicationContext extends AnnotationConfigApplicationContext {
    @Override
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        super.postProcessBeanFactory(beanFactory);
        // 全局设置自定义AopProxyFactory
        ((DefaultListableBeanFactory) beanFactory).setAopProxyFactory(new NoAdviceAopProxyFactory());
    }
}

方案选择建议

  • 若性能瓶颈仅来自请求作用域Bean的代理,优先选方案一:针对性强,轻量且不会影响其他代理场景。
  • 若应用中所有代理都不需要通知,可选择方案二:实现全局统一优化。

验证注意事项

  • 测试需确认作用域Bean的代理逻辑正常(比如请求作用域Bean是否每次请求都能获取新实例)。
  • 压测对比优化前后的CPU使用率和延迟,确保达到预期性能提升。

内容的提问来源于stack exchange,提问作者John Engebretson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:34:56