Handle scoped proxy properly in MBeanExporter
Previously, if a bean has a scoped proxy and is annotated to be exposed to the JMX domain, both the scoped proxy and the target instance were exposed in the JMX domain, resulting in a duplicate entries. Worse, if such bean defines an explicit name, the application wouldn't start because of a name conflict. This commit deals explicitely with scoped proxy and make sure to only expose the relevant bean. Issue: SPR-12529
This commit is contained in:
parent
809ee0d350
commit
cae217de94
|
|
@ -97,4 +97,12 @@ public abstract class ScopedProxyUtils {
|
|||
return TARGET_NAME_PREFIX + originalBeanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify if the {@code beanName} is the name of a bean that references the target
|
||||
* bean within a scoped proxy.
|
||||
*/
|
||||
public static boolean isScopedTarget(String beanName) {
|
||||
return beanName.startsWith(TARGET_NAME_PREFIX);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ import javax.management.modelmbean.ModelMBeanInfo;
|
|||
import javax.management.modelmbean.RequiredModelMBean;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.scope.ScopedProxyUtils;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.aop.target.LazyInitTargetSource;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
|
|
@ -891,8 +892,9 @@ public class MBeanExporter extends MBeanRegistrationSupport implements MBeanExpo
|
|||
if (beanClass != null && callback.include(beanClass, beanName)) {
|
||||
boolean lazyInit = isBeanDefinitionLazyInit(this.beanFactory, beanName);
|
||||
Object beanInstance = (!lazyInit ? this.beanFactory.getBean(beanName) : null);
|
||||
if (!this.beans.containsValue(beanName) && (beanInstance == null ||
|
||||
!CollectionUtils.containsInstance(this.beans.values(), beanInstance))) {
|
||||
if (!ScopedProxyUtils.isScopedTarget(beanName) && !this.beans.containsValue(beanName) &&
|
||||
(beanInstance == null ||
|
||||
!CollectionUtils.containsInstance(this.beans.values(), beanInstance))) {
|
||||
// Not already registered for JMX exposure.
|
||||
this.beans.put(beanName, (beanInstance != null ? beanInstance : beanName));
|
||||
if (logger.isInfoEnabled()) {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.context.annotation.EnableMBeanExport;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.MBeanExportConfiguration;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.context.annotation.ScopedProxyMode;
|
||||
import org.springframework.jmx.export.MBeanExporterTests;
|
||||
import org.springframework.jmx.export.TestDynamicMBean;
|
||||
import org.springframework.jmx.support.MBeanServerFactoryBean;
|
||||
|
|
@ -62,6 +64,20 @@ public class EnableMBeanExportConfigurationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyTargetClassIsExposed() throws Exception {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(
|
||||
ProxyConfiguration.class);
|
||||
try {
|
||||
MBeanServer server = (MBeanServer) ctx.getBean("server");
|
||||
ObjectName oname = ObjectNameManager.getInstance("bean:name=testBean4");
|
||||
assertNotNull(server.getObjectInstance(oname));
|
||||
assertEquals("TEST", server.getAttribute(oname, "Name"));
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlaceholderBased() throws Exception {
|
||||
MockEnvironment env = new MockEnvironment();
|
||||
|
|
@ -151,6 +167,26 @@ public class EnableMBeanExportConfigurationTests {
|
|||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableMBeanExport(server = "server")
|
||||
static class ProxyConfiguration {
|
||||
|
||||
@Bean
|
||||
public MBeanServerFactoryBean server() throws Exception {
|
||||
return new MBeanServerFactoryBean();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Lazy
|
||||
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
|
||||
public AnnotationTestBean testBean() {
|
||||
AnnotationTestBean bean = new AnnotationTestBean();
|
||||
bean.setName("TEST");
|
||||
bean.setAge(100);
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableMBeanExport(server = "${serverName}")
|
||||
|
|
|
|||
Loading…
Reference in New Issue