From 3a4d62fb3a8d567ee6fb5f0e41cc7d094594c893 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 19 Nov 2014 09:57:52 -0800 Subject: [PATCH] Gracefully ignore placeholder exceptions Update BeanTypeRegistry to gracefully ignore LoadBeanClassException and BeanDefinitionStoreException exceptions in the same way as DefaultListableBeanFactory.doGetBeanNamesForType() does. Fixes gh-1955 --- .../condition/BeanTypeRegistry.java | 27 ++++++++++++++- .../condition/ConditionalOnBeanTests.java | 34 +++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java index cb89157038..8edcea801f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java @@ -24,8 +24,12 @@ import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryUtils; +import org.springframework.beans.factory.CannotLoadBeanClassException; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.SmartInitializingSingleton; @@ -54,7 +58,7 @@ import org.springframework.util.StringUtils; */ abstract class BeanTypeRegistry { - public static long check; + static Log logger = LogFactory.getLog(BeanTypeRegistry.class); static final String FACTORY_BEAN_OBJECT_TYPE = "factoryBeanObjectType"; @@ -239,6 +243,12 @@ abstract class BeanTypeRegistry { this.beanTypes.put(name, this.beanFactory.getType(name)); } else if (!this.beanFactory.isAlias(name)) { + addBeanTypeForNonAliasDefinition(name); + } + } + + private void addBeanTypeForNonAliasDefinition(String name) { + try { String factoryName = BeanFactory.FACTORY_BEAN_PREFIX + name; RootBeanDefinition beanDefinition = (RootBeanDefinition) this.beanFactory .getMergedBeanDefinition(name); @@ -256,6 +266,21 @@ abstract class BeanTypeRegistry { } } } + catch (CannotLoadBeanClassException ex) { + // Probably contains a placeholder + logIgnoredError("bean class loading failure for bean", name, ex); + } + catch (BeanDefinitionStoreException ex) { + // Probably contains a placeholder + logIgnoredError("unresolvable metadata in bean definition", name, ex); + } + } + + private void logIgnoredError(String message, String name, Exception ex) { + if (BeanTypeRegistry.logger.isDebugEnabled()) { + BeanTypeRegistry.logger.debug("Ignoring " + message + " '" + name + "'", + ex); + } } private boolean requiresEagerInit(String factoryBeanName) { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java index 4891a2b01a..6ab321b2ff 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java @@ -19,11 +19,17 @@ package org.springframework.boot.autoconfigure.condition; import java.util.Date; import org.junit.Test; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.ImportResource; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.type.AnnotationMetadata; import org.springframework.scheduling.annotation.EnableScheduling; import static org.junit.Assert.assertEquals; @@ -116,6 +122,14 @@ public class ConditionalOnBeanTests { assertFalse(this.context.containsBean("bar")); } + @Test + public void withPropertyPlaceholderClassName() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, "mybeanclass=java.lang.String"); + this.context.register(PropertySourcesPlaceholderConfigurer.class, + WithPropertyPlaceholderClassName.class, OnBeanClassConfiguration.class); + this.context.refresh(); + } + @Configuration @ConditionalOnBean(name = "foo") protected static class OnBeanNameConfiguration { @@ -189,4 +203,24 @@ public class ConditionalOnBeanTests { @Import(OnBeanNameConfiguration.class) protected static class CombinedXmlConfiguration { } + + @Configuration + @Import(WithPropertyPlaceholderClassNameRegistrar.class) + protected static class WithPropertyPlaceholderClassName { + + } + + protected static class WithPropertyPlaceholderClassNameRegistrar implements + ImportBeanDefinitionRegistrar { + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + RootBeanDefinition bd = new RootBeanDefinition(); + bd.setBeanClassName("${mybeanclass}"); + registry.registerBeanDefinition("mybean", bd); + } + + } + }