Merge branch '1.3.x'

pull/6645/merge
Andy Wilkinson 8 years ago
commit 6df279d3a1

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2015 the original author or authors. * Copyright 2012-2016 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -37,6 +37,7 @@ import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
@ -137,8 +138,34 @@ abstract class BeanTypeRegistry {
.getBeanDefinition(definition.getFactoryBeanName()); .getBeanDefinition(definition.getFactoryBeanName());
Class<?> factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(), Class<?> factoryClass = ClassUtils.forName(factoryDefinition.getBeanClassName(),
beanFactory.getBeanClassLoader()); beanFactory.getBeanClassLoader());
return ReflectionUtils.findMethod(factoryClass, Method uniqueMethod = null;
definition.getFactoryMethodName()); for (Method candidate : getCandidateFactoryMethods(definition, factoryClass)) {
if (candidate.getName().equals(definition.getFactoryMethodName())) {
if (uniqueMethod == null) {
uniqueMethod = candidate;
}
else if (!matchingArguments(candidate, uniqueMethod)) {
return null;
}
}
}
return uniqueMethod;
}
private Method[] getCandidateFactoryMethods(BeanDefinition definition,
Class<?> factoryClass) {
return shouldConsiderNonPublicMethods(definition)
? ReflectionUtils.getAllDeclaredMethods(factoryClass)
: factoryClass.getMethods();
}
private boolean shouldConsiderNonPublicMethods(BeanDefinition definition) {
return (definition instanceof AbstractBeanDefinition)
&& ((AbstractBeanDefinition) definition).isNonPublicAccessAllowed();
}
private boolean matchingArguments(Method candidate, Method current) {
return Arrays.equals(candidate.getParameterTypes(), current.getParameterTypes());
} }
private Class<?> getDirectFactoryBeanGeneric( private Class<?> getDirectFactoryBeanGeneric(

@ -25,10 +25,15 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.scan.ScannedFactoryBeanConfiguration;
import org.springframework.boot.autoconfigure.condition.scan.ScannedFactoryBeanWithBeanMethodArgumentsConfiguration;
import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ImportResource; import org.springframework.context.annotation.ImportResource;
@ -140,6 +145,27 @@ public class ConditionalOnMissingBeanTests {
.isEqualTo("fromFactory"); .isEqualTo("fromFactory");
} }
@Test
public void testOnMissingBeanConditionWithComponentScannedFactoryBean() {
this.context.register(ComponentScannedFactoryBeanBeanMethodConfiguration.class,
ConditionalOnFactoryBean.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(ExampleBean.class).toString())
.isEqualTo("fromFactory");
}
@Test
public void testOnMissingBeanConditionWithComponentScannedFactoryBeanWithBeanMethodArguments() {
this.context.register(
ComponentScannedFactoryBeanBeanMethodWithArgumentsConfiguration.class,
ConditionalOnFactoryBean.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(ExampleBean.class).toString())
.isEqualTo("fromFactory");
}
@Test @Test
public void testOnMissingBeanConditionWithFactoryBeanWithBeanMethodArguments() { public void testOnMissingBeanConditionWithFactoryBeanWithBeanMethodArguments() {
this.context.register(FactoryBeanWithBeanMethodArgumentsConfiguration.class, this.context.register(FactoryBeanWithBeanMethodArgumentsConfiguration.class,
@ -264,6 +290,18 @@ public class ConditionalOnMissingBeanTests {
} }
@Configuration
@ComponentScan(basePackages = "org.springframework.boot.autoconfigure.condition.scan", includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ScannedFactoryBeanConfiguration.class))
protected static class ComponentScannedFactoryBeanBeanMethodConfiguration {
}
@Configuration
@ComponentScan(basePackages = "org.springframework.boot.autoconfigure.condition.scan", includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ScannedFactoryBeanWithBeanMethodArgumentsConfiguration.class))
protected static class ComponentScannedFactoryBeanBeanMethodWithArgumentsConfiguration {
}
@Configuration @Configuration
protected static class FactoryBeanWithBeanMethodArgumentsConfiguration { protected static class FactoryBeanWithBeanMethodArgumentsConfiguration {

@ -0,0 +1,39 @@
/*
* Copyright 2012-2016 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.boot.autoconfigure.condition.scan;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBeanTests.ExampleBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBeanTests.ExampleFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configuration for a factory bean produced by a bean method on a configuration class
* found via component scanning.
*
* @author Andy Wilkinson
*/
@Configuration
public class ScannedFactoryBeanConfiguration {
@Bean
public FactoryBean<ExampleBean> exampleBeanFactoryBean() {
return new ExampleFactoryBean("foo");
}
}

@ -0,0 +1,46 @@
/*
* Copyright 2012-2016 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.boot.autoconfigure.condition.scan;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBeanTests.ExampleFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Configuration for a factory bean produced by a bean method with arguments on a
* configuration class found via component scanning.
*
* @author Andy Wilkinson
*/
@Configuration
public class ScannedFactoryBeanWithBeanMethodArgumentsConfiguration {
@Bean
public Foo foo() {
return new Foo();
}
@Bean
public ExampleFactoryBean exampleBeanFactoryBean(Foo foo) {
return new ExampleFactoryBean("foo");
}
static class Foo {
}
}
Loading…
Cancel
Save