From 197c2d7ca2fe9cf4c6fe1af4b6f6d6fef69079ea Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sun, 13 Dec 2009 23:28:07 +0000 Subject: [PATCH] MBeanExporter detects FactoryBean-exported resources independent from declaration order git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@2643 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../jmx/export/MBeanExporter.java | 67 ++++++++++--------- .../AnnotationLazyInitMBeanTests.java | 5 ++ .../annotation/AnnotationTestBeanFactory.java | 45 +++++++++++++ .../FactoryCreatedAnnotationTestBean.java | 25 +++++++ .../jmx/export/annotation/lazyAssembling.xml | 12 ++-- .../jmx/export/annotation/lazyNaming.xml | 4 +- 6 files changed, 120 insertions(+), 38 deletions(-) create mode 100644 org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java create mode 100644 org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java diff --git a/org.springframework.context/src/main/java/org/springframework/jmx/export/MBeanExporter.java b/org.springframework.context/src/main/java/org/springframework/jmx/export/MBeanExporter.java index 87d0683cf0b..333ae5fb736 100644 --- a/org.springframework.context/src/main/java/org/springframework/jmx/export/MBeanExporter.java +++ b/org.springframework.context/src/main/java/org/springframework/jmx/export/MBeanExporter.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -43,11 +44,11 @@ import org.springframework.aop.target.LazyInitTargetSource; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; +import org.springframework.beans.factory.CannotLoadBeanClassException; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.NoSuchBeanDefinitionException; -import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.Constants; import org.springframework.jmx.export.assembler.AutodetectCapableMBeanInfoAssembler; @@ -142,7 +143,7 @@ public class MBeanExporter extends MBeanRegistrationSupport /** The autodetect mode to use for this MBeanExporter */ private Integer autodetectMode; - /** Whether to eagerly init candidate beans when autodetecting MBeans */ + /** Whether to eagerly initialize candidate beans when autodetecting MBeans */ private boolean allowEagerInit = false; /** Indicates whether Spring should modify generated ObjectNames */ @@ -381,14 +382,13 @@ public class MBeanExporter extends MBeanRegistrationSupport * ListableBeanFactory is required). * @see #setBeans * @see #setAutodetect - * @throws IllegalArgumentException if the supplied beanFactory is not a {@link ListableBeanFactory}. */ public void setBeanFactory(BeanFactory beanFactory) { if (beanFactory instanceof ListableBeanFactory) { this.beanFactory = (ListableBeanFactory) beanFactory; } else { - logger.info("MBeanExporter not running in a ListableBeanFactory: Autodetection of MBeans not available."); + logger.info("MBeanExporter not running in a ListableBeanFactory: autodetection of MBeans not available."); } } @@ -537,17 +537,8 @@ public class MBeanExporter extends MBeanRegistrationSupport * @see org.springframework.beans.factory.config.BeanDefinition#isLazyInit */ protected boolean isBeanDefinitionLazyInit(ListableBeanFactory beanFactory, String beanName) { - if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { - return false; - } - try { - BeanDefinition bd = ((ConfigurableListableBeanFactory) beanFactory).getBeanDefinition(beanName); - return bd.isLazyInit(); - } - catch (NoSuchBeanDefinitionException ex) { - // Probably a directly registered singleton. - return false; - } + return (beanFactory instanceof ConfigurableListableBeanFactory && beanFactory.containsBeanDefinition(beanName) && + ((ConfigurableListableBeanFactory) beanFactory).getBeanDefinition(beanName).isLazyInit()); } /** @@ -594,7 +585,7 @@ public class MBeanExporter extends MBeanRegistrationSupport // Plain bean instance -> register it directly. if (this.beanFactory != null) { Map beansOfSameType = - this.beanFactory.getBeansOfType(mapValue.getClass(), false, false); + this.beanFactory.getBeansOfType(mapValue.getClass(), false, this.allowEagerInit); for (Map.Entry entry : beansOfSameType.entrySet()) { if (entry.getValue() == mapValue) { String beanName = entry.getKey(); @@ -875,26 +866,38 @@ public class MBeanExporter extends MBeanRegistrationSupport * whether to include a bean or not */ private void autodetect(AutodetectCallback callback) { - String[] beanNames = this.beanFactory.getBeanNamesForType(Object.class, true, this.allowEagerInit); + Set beanNames = new LinkedHashSet(this.beanFactory.getBeanDefinitionCount()); + beanNames.addAll(Arrays.asList(this.beanFactory.getBeanDefinitionNames())); + if (this.beanFactory instanceof ConfigurableBeanFactory) { + beanNames.addAll(Arrays.asList(((ConfigurableBeanFactory) this.beanFactory).getSingletonNames())); + } for (String beanName : beanNames) { if (!isExcluded(beanName)) { - Class beanClass = this.beanFactory.getType(beanName); - 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))) { - // Not already registered for JMX exposure. - this.beans.put(beanName, (beanInstance != null ? beanInstance : beanName)); - if (logger.isInfoEnabled()) { - logger.info("Bean with name '" + beanName + "' has been autodetected for JMX exposure"); + try { + Class beanClass = this.beanFactory.getType(beanName); + 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))) { + // Not already registered for JMX exposure. + this.beans.put(beanName, (beanInstance != null ? beanInstance : beanName)); + if (logger.isInfoEnabled()) { + logger.info("Bean with name '" + beanName + "' has been autodetected for JMX exposure"); + } + } + else { + if (logger.isDebugEnabled()) { + logger.debug("Bean with name '" + beanName + "' is already registered for JMX exposure"); + } } } - else { - if (logger.isDebugEnabled()) { - logger.debug("Bean with name '" + beanName + "' is already registered for JMX exposure"); - } + } + catch (CannotLoadBeanClassException ex) { + if (this.allowEagerInit) { + throw ex; } + // otherwise ignore beans where the class is not resolvable } } } diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java index f75bd7d50f4..3e323e7ca67 100644 --- a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationLazyInitMBeanTests.java @@ -57,6 +57,11 @@ public class AnnotationLazyInitMBeanTests extends TestCase { String name = (String) server.getAttribute(oname, "Name"); assertEquals("Invalid name returned", "TEST", name); + oname = ObjectNameManager.getInstance("bean:name=testBean5"); + assertNotNull(server.getObjectInstance(oname)); + name = (String) server.getAttribute(oname, "Name"); + assertEquals("Invalid name returned", "FACTORY", name); + oname = ObjectNameManager.getInstance("spring:mbean=true"); assertNotNull(server.getObjectInstance(oname)); name = (String) server.getAttribute(oname, "Name"); diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java new file mode 100644 index 00000000000..c8b71e2b610 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/AnnotationTestBeanFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.export.annotation; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.jmx.IJmxTestBean; + +/** + * @author Juergen Hoeller + */ +public class AnnotationTestBeanFactory implements FactoryBean { + + private final FactoryCreatedAnnotationTestBean instance = new FactoryCreatedAnnotationTestBean(); + + public AnnotationTestBeanFactory() { + this.instance.setName("FACTORY"); + } + + public IJmxTestBean getObject() throws Exception { + return this.instance; + } + + public Class getObjectType() { + return FactoryCreatedAnnotationTestBean.class; + } + + public boolean isSingleton() { + return true; + } + +} diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java new file mode 100644 index 00000000000..a8a9b3f6706 --- /dev/null +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/FactoryCreatedAnnotationTestBean.java @@ -0,0 +1,25 @@ +/* + * Copyright 2002-2009 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jmx.export.annotation; + +/** + * @author Juergen Hoeller + */ +@ManagedResource(objectName = "bean:name=testBean5") +public class FactoryCreatedAnnotationTestBean extends AnnotationTestBean { + +} diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml index b11a795aac3..c1d7afdab64 100644 --- a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyAssembling.xml @@ -5,21 +5,25 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> - + - + - + - + + + + + diff --git a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyNaming.xml b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyNaming.xml index 92e07746efe..15f14a86649 100644 --- a/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyNaming.xml +++ b/org.springframework.context/src/test/java/org/springframework/jmx/export/annotation/lazyNaming.xml @@ -5,9 +5,9 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> - + - +