我在我的Spring XML描述符中使用原型范围的bean定义来配置默认属性(这些bean有许多属性)然后我用a getBean(beanName, ctorArgs[])来调用应用程序上下文来创建实例.
bean定义需要2-3个构造函数参数,这些参数提供逻辑上唯一的键,用于JMX的键属性ObjectName等.另外,构造函数参数写入的变量是final.
我所看到的是,当应用程序上下文刷新时,它会尝试实例化这些原型,这看起来与你想要原型的完全相反.它们是模板,而不是实际的实例.为了解决这个问题,我一直在使用伪造的ctor值配置原型,以便实例化这些伪造的bean实例,我只是在代码中过滤掉创建的MBean.
我的问题是,如何配置应用程序上下文来注册这些原型bean定义,但是在我打电话之前不实例化它们getBean?
问题比我最初想的要复杂一些.事实上,lazy是原型范围bean的默认行为.我挖了一点,我设法重现你的问题,找到解决方案.那么问题是什么?
您可能已<aop:scoped-proxy/>启用或(@ComponentScan(scopedProxy=...)等效).在上下文刷新期间,Spring用原型ClosedMetricSubscriberFeed代理包装你的原型bean().它使用类代理,因为(a)选择类代理或(b)类没有接口.
基于类的代理基本上是bean的CGLIB子类,必须调用(由于JVM规则)基类的构造函数.CGLIB生成的类总是调用no-arg构造函数.
我知道这听起来很复杂,这就是你能做的:
禁用<aop:scoped-proxy/>.就像那样.
提供一个虚拟的无参数构造函数并弃用它以防万一.不幸的是,你将不得不发现这样的虚假实例.请注意,在这种情况下,类的类型为:``.
从类中提取接口并使用接口作为范围代理:
.
@Scope(
value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,
proxyMode = ScopedProxyMode.INTERFACES)
Run Code Online (Sandbox Code Playgroud)
使用带@Lazy注释的延迟初始化或lazy-init="true"(参见参考文档中的4.4.4 Lazy-initialized beans)配置属性.
<bean id="proto" class="MyPrototype" scope="prototype" lazy-init="true"/>
Run Code Online (Sandbox Code Playgroud)
要么:
@Service
@Scope("prototype")
@Lazy
public class MyPrototype {/*...*/}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4849 次 |
| 最近记录: |