问题
I am using Spring in conjunction with its MBeanExporter
. I have a prototype bean definition which should only be instantiated when a call to ApplicationContext.getBean()
is made. However, the MBeanExporter
is (incorrectly) instantiating an instance of the prototype bean when bootstrapping the container.
I found this bug report from ages ago, with no notable response.
This seems to me like it must be a common scenario, so I feel like I must be missing something. It's important that my prototype not be instantiated ahead of time, and that I can use MBeanExporter
to make my JMX integration simpler. Can anyone explain what I'm doing wrong?
For reference, my spring config looks like this:
<bean id="foo" class="MyPrototypeClassName" scope="prototype"/>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.IdentityNamingStrategy"/>
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
</bean>
回答1:
I've found something of a workaround, but it's clunky so I suspect it's not best practices. I have simply changed my exporter config to:
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
<property name="excludedBeans">
<list>
<value>foo</value>
</list>
</property>
</bean>
That way the auto-exporter ignores my prototype bean. Consequently, my prototype bean can now take a reference to the MBeanExporter
(previously this was causing a unresolvable dependency cycle). So now my prototype can register and unregister itself in JMX at appropriate points.
If anyone can weigh in on whether this is a good/bad approach, I'd appreciate it.
回答2:
You could use a custom marker interface like MyJmxAutodetectExclude
and extend Spring MetadataMBeanInfoAssembler
. This way you don't need to tweak your context.xml each time you refactor your code
public class MyMBeanInfoAssembler extends MetadataMBeanInfoAssembler {
@Override
public boolean includeBean(final Class<?> beanClass, final String beanName) {
if (super.includeBean(beanClass, beanName)) {
List<Class<?>> list = Arrays.asList(beanClass.getInterfaces());
if (list.contains(MyJmxAutodetectExclude.class)) {
return false;
}
return true;
}
return false;
}
}
来源:https://stackoverflow.com/questions/12748087/spring-prototypes-and-mbeanexporter