当使用Spring并结合ProxyFactoryBean和@Inject Provider 时,最终在启动期间会创建大量对象。我将原因确定为DefaultListableBeanFactory.doGetBeanNamesForType方法。通过遍历所有bean定义并搜索可以满足提供者通用参数的定义,可以满足“ @Inject Provider ”的要求。遇到FactoryBean时,首先将其完全初始化,然后才对其进行查询getObjectType()。但是,ProxyFactoryBean通常在applicationContext.xml中设置,并且依赖于它们代理的bean。完全初始化ProxyFactoryBean会导致内部bean的实例化。除非那时无法实例化内部Bean,否则所有这些都很好。因为它依赖于其他一些直到原始bean(带有Provider的bean)才能初始化的bean。没有循环依赖性,只有过度渴望的初始化。例:class Bean1 { @Inject Provider<X> provider;}class Bean2 { @Inject Bean1 bean1;}applicationContext.xml:<bean id="bean1" class="com.rb.springissues.sample.Bean1"/><bean id="bean2" class="com.rb.springissues.sample.Bean2"/><bean id="bean2Factory" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="bean2"/> <property name="proxyTargetClass" value="true"/></bean>在上面的示例中,流程是(由Spring完全管理的):实例化bean1。尝试初始化bean1,发现它具有Provider<X>。遍历上下文中的所有BeanDefinition。对于每个:如果它是“普通” bean,请评估该类以查看其是否适合。如果它是FactoryBean,请尝试实例化并初始化FactoryBean,以查看“ getObjectType()”将返回什么。为了初始化bean2Factory,需要向其提供bean2实例。因此,Spring尝试实例化并初始化bean2。但是-bean2无法初始化,因为它依赖于bean1-导致Spring抛出循环依赖错误。如果FactoryObject是正确创建的,Spring现在会询问类型并缓存响应(“好路径”)。如果发生异常(循环依赖项错误),则会捕获并忽略该异常,但结果不会被缓存-因此,如果我们得到另一个bean,它将再次执行相同的操作(一次又一次...)有关完整描述和示例,请参见https://github.com/bironran/spring_issues_proxy_factory。我已经观察到现实世界中的应用程序实例化了约500个已定义的bean,并由于这个问题尝试初始化超过300,000个对象(一次又一次地初始化相同的bean)。启动延迟了几分钟,并且GC达到峰值。此外,此问题呈指数增长-无法解决的任何新依赖关系都可能使应用程序加载时间加倍。很想听听有关如何解决的建议(请参阅github项目)。 (adsbygoogle = window.adsbygoogle || []).push({}); 最佳答案 事实证明,解决方案很容易-将<property name="target" ref="bean2"/>替换为:<property name="targetName"> <idref bean="bean2"/></property><property name="targetClass" value="com.rb.springissues.sample.Bean2"/>这会导致bean2的绑定延迟-因此可以在没有Bean2实例的情况下初始化工厂。 (adsbygoogle = window.adsbygoogle || []).push({});
08-06 12:14