Merge branch '2.3.x'

Closes gh-22198
pull/22207/head
Andy Wilkinson 4 years ago
commit ecc50d179d

@ -24,12 +24,14 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
@ -166,7 +168,13 @@ class OnBeanCondition extends FilteringSpringBootCondition implements Configurat
for (String type : spec.getTypes()) {
Collection<String> typeMatches = getBeanNamesForType(classLoader, considerHierarchy, beanFactory, type,
parameterizedContainers);
typeMatches.removeAll(beansIgnoredByType);
Iterator<String> iterator = typeMatches.iterator();
while (iterator.hasNext()) {
String match = iterator.next();
if (beansIgnoredByType.contains(match) || ScopedProxyUtils.isScopedTarget(match)) {
iterator.remove();
}
}
if (typeMatches.isEmpty()) {
result.recordUnmatchedType(type);
}

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
@ -16,16 +16,16 @@
package org.springframework.boot.autoconfigure.condition;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Tests for {@link ConditionalOnSingleCandidate @ConditionalOnSingleCandidate}.
@ -35,117 +35,114 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
*/
class ConditionalOnSingleCandidateTests {
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
@AfterEach
void close() {
if (this.context != null) {
this.context.close();
}
}
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner();
@Test
void singleCandidateNoCandidate() {
load(OnBeanSingleCandidateConfiguration.class);
assertThat(this.context.containsBean("baz")).isFalse();
this.contextRunner.withUserConfiguration(OnBeanSingleCandidateConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("consumer"));
}
@Test
void singleCandidateOneCandidate() {
load(FooConfiguration.class, OnBeanSingleCandidateConfiguration.class);
assertThat(this.context.containsBean("baz")).isTrue();
assertThat(this.context.getBean("baz")).isEqualTo("foo");
this.contextRunner.withUserConfiguration(AlphaConfiguration.class, OnBeanSingleCandidateConfiguration.class)
.run((context) -> {
assertThat(context).hasBean("consumer");
assertThat(context.getBean("consumer")).isEqualTo("alpha");
});
}
@Test
void singleCandidateOneScopedProxyCandidate() {
this.contextRunner
.withUserConfiguration(AlphaScopedProxyConfiguration.class, OnBeanSingleCandidateConfiguration.class)
.run((context) -> {
assertThat(context).hasBean("consumer");
assertThat(context.getBean("consumer").toString()).isEqualTo("alpha");
});
}
@Test
void singleCandidateInAncestorsOneCandidateInCurrent() {
load();
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.register(FooConfiguration.class, OnBeanSingleCandidateInAncestorsConfiguration.class);
child.setParent(this.context);
child.refresh();
assertThat(child.containsBean("baz")).isFalse();
child.close();
this.contextRunner.run((parent) -> this.contextRunner
.withUserConfiguration(AlphaConfiguration.class, OnBeanSingleCandidateInAncestorsConfiguration.class)
.withParent(parent).run((child) -> assertThat(child).doesNotHaveBean("consumer")));
}
@Test
void singleCandidateInAncestorsOneCandidateInParent() {
load(FooConfiguration.class);
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.register(OnBeanSingleCandidateInAncestorsConfiguration.class);
child.setParent(this.context);
child.refresh();
assertThat(child.containsBean("baz")).isTrue();
assertThat(child.getBean("baz")).isEqualTo("foo");
child.close();
this.contextRunner.withUserConfiguration(AlphaConfiguration.class)
.run((parent) -> this.contextRunner
.withUserConfiguration(OnBeanSingleCandidateInAncestorsConfiguration.class).withParent(parent)
.run((child) -> {
assertThat(child).hasBean("consumer");
assertThat(child.getBean("consumer")).isEqualTo("alpha");
}));
}
@Test
void singleCandidateInAncestorsOneCandidateInGrandparent() {
load(FooConfiguration.class);
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
parent.setParent(this.context);
parent.refresh();
AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext();
child.register(OnBeanSingleCandidateInAncestorsConfiguration.class);
child.setParent(parent);
child.refresh();
assertThat(child.containsBean("baz")).isTrue();
assertThat(child.getBean("baz")).isEqualTo("foo");
child.close();
parent.close();
this.contextRunner.withUserConfiguration(AlphaConfiguration.class)
.run((grandparent) -> this.contextRunner.withParent(grandparent)
.run((parent) -> this.contextRunner
.withUserConfiguration(OnBeanSingleCandidateInAncestorsConfiguration.class)
.withParent(parent).run((child) -> {
assertThat(child).hasBean("consumer");
assertThat(child.getBean("consumer")).isEqualTo("alpha");
})));
}
@Test
void singleCandidateMultipleCandidates() {
load(FooConfiguration.class, BarConfiguration.class, OnBeanSingleCandidateConfiguration.class);
assertThat(this.context.containsBean("baz")).isFalse();
this.contextRunner
.withUserConfiguration(AlphaConfiguration.class, BravoConfiguration.class,
OnBeanSingleCandidateConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("consumer"));
}
@Test
void singleCandidateMultipleCandidatesOnePrimary() {
load(FooPrimaryConfiguration.class, BarConfiguration.class, OnBeanSingleCandidateConfiguration.class);
assertThat(this.context.containsBean("baz")).isTrue();
assertThat(this.context.getBean("baz")).isEqualTo("foo");
this.contextRunner.withUserConfiguration(AlphaPrimaryConfiguration.class, BravoConfiguration.class,
OnBeanSingleCandidateConfiguration.class).run((context) -> {
assertThat(context).hasBean("consumer");
assertThat(context.getBean("consumer")).isEqualTo("alpha");
});
}
@Test
void singleCandidateMultipleCandidatesMultiplePrimary() {
load(FooPrimaryConfiguration.class, BarPrimaryConfiguration.class, OnBeanSingleCandidateConfiguration.class);
assertThat(this.context.containsBean("baz")).isFalse();
this.contextRunner
.withUserConfiguration(AlphaPrimaryConfiguration.class, BravoPrimaryConfiguration.class,
OnBeanSingleCandidateConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("consumer"));
}
@Test
void invalidAnnotationTwoTypes() {
assertThatIllegalStateException().isThrownBy(() -> load(OnBeanSingleCandidateTwoTypesConfiguration.class))
.withCauseInstanceOf(IllegalArgumentException.class)
.withMessageContaining(OnBeanSingleCandidateTwoTypesConfiguration.class.getName());
this.contextRunner.withUserConfiguration(OnBeanSingleCandidateTwoTypesConfiguration.class).run((context) -> {
assertThat(context).hasFailed();
assertThat(context).getFailure().hasCauseInstanceOf(IllegalArgumentException.class)
.hasMessageContaining(OnBeanSingleCandidateTwoTypesConfiguration.class.getName());
});
}
@Test
void invalidAnnotationNoType() {
assertThatIllegalStateException().isThrownBy(() -> load(OnBeanSingleCandidateNoTypeConfiguration.class))
.withCauseInstanceOf(IllegalArgumentException.class)
.withMessageContaining(OnBeanSingleCandidateNoTypeConfiguration.class.getName());
this.contextRunner.withUserConfiguration(OnBeanSingleCandidateNoTypeConfiguration.class).run((context) -> {
assertThat(context).hasFailed();
assertThat(context).getFailure().hasCauseInstanceOf(IllegalArgumentException.class)
.hasMessageContaining(OnBeanSingleCandidateNoTypeConfiguration.class.getName());
});
}
@Test
void singleCandidateMultipleCandidatesInContextHierarchy() {
load(FooPrimaryConfiguration.class, BarConfiguration.class);
try (AnnotationConfigApplicationContext child = new AnnotationConfigApplicationContext()) {
child.setParent(this.context);
child.register(OnBeanSingleCandidateConfiguration.class);
child.refresh();
assertThat(child.containsBean("baz")).isTrue();
assertThat(child.getBean("baz")).isEqualTo("foo");
}
}
private void load(Class<?>... classes) {
if (classes.length > 0) {
this.context.register(classes);
}
this.context.refresh();
this.contextRunner.withUserConfiguration(AlphaPrimaryConfiguration.class, BravoConfiguration.class)
.run((parent) -> this.contextRunner.withUserConfiguration(OnBeanSingleCandidateConfiguration.class)
.withParent(parent).run((child) -> {
assertThat(child).hasBean("consumer");
assertThat(child.getBean("consumer")).isEqualTo("alpha");
}));
}
@Configuration(proxyBeanMethods = false)
@ -153,7 +150,7 @@ class ConditionalOnSingleCandidateTests {
static class OnBeanSingleCandidateConfiguration {
@Bean
String baz(String s) {
CharSequence consumer(CharSequence s) {
return s;
}
@ -164,7 +161,7 @@ class ConditionalOnSingleCandidateTests {
static class OnBeanSingleCandidateInAncestorsConfiguration {
@Bean
String baz(String s) {
CharSequence consumer(CharSequence s) {
return s;
}
@ -183,43 +180,54 @@ class ConditionalOnSingleCandidateTests {
}
@Configuration(proxyBeanMethods = false)
static class FooConfiguration {
static class AlphaConfiguration {
@Bean
String foo() {
return "foo";
String alpha() {
return "alpha";
}
}
@Configuration(proxyBeanMethods = false)
static class FooPrimaryConfiguration {
static class AlphaPrimaryConfiguration {
@Bean
@Primary
String foo() {
return "foo";
String alpha() {
return "alpha";
}
}
@Configuration(proxyBeanMethods = false)
static class AlphaScopedProxyConfiguration {
@Bean
@Scope(proxyMode = ScopedProxyMode.INTERFACES)
String alpha() {
return "alpha";
}
}
@Configuration(proxyBeanMethods = false)
static class BarConfiguration {
static class BravoConfiguration {
@Bean
String bar() {
return "bar";
String bravo() {
return "bravo";
}
}
@Configuration(proxyBeanMethods = false)
static class BarPrimaryConfiguration {
static class BravoPrimaryConfiguration {
@Bean
@Primary
String bar() {
return "bar";
String bravo() {
return "bravo";
}
}

Loading…
Cancel
Save