Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
c4ddce6b
Commit
c4ddce6b
authored
Apr 07, 2015
by
Phillip Webb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Polish
parent
8b1022ef
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
54 additions
and
51 deletions
+54
-51
ConditionalOnSingleCandidate.java
...autoconfigure/condition/ConditionalOnSingleCandidate.java
+9
-8
OnBeanCondition.java
...amework/boot/autoconfigure/condition/OnBeanCondition.java
+26
-34
ConditionalOnSingleCandidateTests.java
...onfigure/condition/ConditionalOnSingleCandidateTests.java
+19
-9
No files found.
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidate.java
View file @
c4ddce6b
...
@@ -30,15 +30,14 @@ import org.springframework.context.annotation.Conditional;
...
@@ -30,15 +30,14 @@ import org.springframework.context.annotation.Conditional;
* {@link Conditional} that only matches when the specified bean class is already
* {@link Conditional} that only matches when the specified bean class is already
* contained in the {@link BeanFactory} and a single candidate can be determined.
* contained in the {@link BeanFactory} and a single candidate can be determined.
* <p>
* <p>
* The conditional will also match if multiple matching bean instances are already
* The condition will also match if multiple matching bean instances are already contained
* contained in the {@link BeanFactory} but a primary candidate has been defined;
* in the {@link BeanFactory} but a primary candidate has been defined; essentially, the
* essentially, the condition match if auto-wiring a bean with the defined type
* condition match if auto-wiring a bean with the defined type will succeed.
* will succeed.
*
*
* @author Stephane Nicoll
* @author Stephane Nicoll
* @since 1.3.0
* @since 1.3.0
*/
*/
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
@Documented
@Conditional
(
OnBeanCondition
.
class
)
@Conditional
(
OnBeanCondition
.
class
)
...
@@ -48,8 +47,9 @@ public @interface ConditionalOnSingleCandidate {
...
@@ -48,8 +47,9 @@ public @interface ConditionalOnSingleCandidate {
* The class type of bean that should be checked. The condition match if the class
* The class type of bean that should be checked. The condition match if the class
* specified is contained in the {@link ApplicationContext} and a primary candidate
* specified is contained in the {@link ApplicationContext} and a primary candidate
* exists in case of multiple instances.
* exists in case of multiple instances.
* <p>This attribute may <strong>not</strong> be used in conjunction with
* <p>
* {@link #type()}, but it may be used instead of {@link #type()}.
* This attribute may <strong>not</strong> be used in conjunction with {@link #type()}
* , but it may be used instead of {@link #type()}.
* @return the class type of the bean to check
* @return the class type of the bean to check
*/
*/
Class
<?>
value
()
default
Object
.
class
;
Class
<?>
value
()
default
Object
.
class
;
...
@@ -58,7 +58,8 @@ public @interface ConditionalOnSingleCandidate {
...
@@ -58,7 +58,8 @@ public @interface ConditionalOnSingleCandidate {
* The class type name of bean that should be checked. The condition matches if the
* The class type name of bean that should be checked. The condition matches if the
* class specified is contained in the {@link ApplicationContext} and a primary
* class specified is contained in the {@link ApplicationContext} and a primary
* candidate exists in case of multiple instances.
* candidate exists in case of multiple instances.
* <p>This attribute may <strong>not</strong> be used in conjunction with
* <p>
* This attribute may <strong>not</strong> be used in conjunction with
* {@link #value()}, but it may be used instead of {@link #value()}.
* {@link #value()}, but it may be used instead of {@link #value()}.
* @return the class type name of the bean to check
* @return the class type name of the bean to check
*/
*/
...
...
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java
View file @
c4ddce6b
...
@@ -24,12 +24,10 @@ import java.util.Collection;
...
@@ -24,12 +24,10 @@ import java.util.Collection;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.List
;
import
java.util.ListIterator
;
import
java.util.Set
;
import
java.util.Set
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.HierarchicalBeanFactory
;
import
org.springframework.beans.factory.HierarchicalBeanFactory
;
import
org.springframework.beans.factory.ListableBeanFactory
;
import
org.springframework.beans.factory.ListableBeanFactory
;
...
@@ -100,15 +98,13 @@ public class OnBeanCondition extends SpringBootCondition implements
...
@@ -100,15 +98,13 @@ public class OnBeanCondition extends SpringBootCondition implements
return
ConditionOutcome
.
noMatch
(
"@ConditionalOnSingleCandidate "
+
spec
return
ConditionOutcome
.
noMatch
(
"@ConditionalOnSingleCandidate "
+
spec
+
" found no beans"
);
+
" found no beans"
);
}
}
else
if
(
hasSingleAutowireCandidate
(
context
.
getBeanFactory
(),
matching
))
{
else
if
(!
hasSingleAutowireCandidate
(
context
.
getBeanFactory
(),
matching
))
{
matchMessage
.
append
(
"@ConditionalOnSingleCandidate "
+
spec
+
" found a primary "
+
"candidate amongst the following "
+
matching
);
}
else
{
return
ConditionOutcome
.
noMatch
(
"@ConditionalOnSingleCandidate "
+
spec
return
ConditionOutcome
.
noMatch
(
"@ConditionalOnSingleCandidate "
+
spec
+
" found no primary candidate amongst the"
+
" found no primary candidate amongst the"
+
" following "
+
" following "
+
matching
);
+
matching
);
}
}
matchMessage
.
append
(
"@ConditionalOnSingleCandidate "
+
spec
+
" found "
+
"a primary candidate amongst the following "
+
matching
);
}
}
if
(
metadata
.
isAnnotated
(
ConditionalOnMissingBean
.
class
.
getName
()))
{
if
(
metadata
.
isAnnotated
(
ConditionalOnMissingBean
.
class
.
getName
()))
{
BeanSearchSpec
spec
=
new
BeanSearchSpec
(
context
,
metadata
,
BeanSearchSpec
spec
=
new
BeanSearchSpec
(
context
,
metadata
,
...
@@ -221,23 +217,21 @@ public class OnBeanCondition extends SpringBootCondition implements
...
@@ -221,23 +217,21 @@ public class OnBeanCondition extends SpringBootCondition implements
}
}
}
}
private
boolean
hasSingleAutowireCandidate
(
ConfigurableListableBeanFactory
beanFactory
,
private
boolean
hasSingleAutowireCandidate
(
List
<
String
>
beans
)
{
ConfigurableListableBeanFactory
beanFactory
,
List
<
String
>
beanNames
)
{
return
(
beanNames
.
size
()
==
1
||
getPrimaryBeans
(
beanFactory
,
beanNames
).
size
()
==
1
);
}
if
(
beans
.
size
()
==
1
)
{
private
List
<
String
>
getPrimaryBeans
(
ConfigurableListableBeanFactory
beanFactory
,
return
true
;
List
<
String
>
beanNames
)
{
}
List
<
String
>
primaryBeans
=
new
ArrayList
<
String
>();
boolean
primaryFound
=
false
;
for
(
String
beanName
:
beanNames
)
{
for
(
String
bean
:
beans
)
{
BeanDefinition
beanDefinition
=
beanFactory
.
getBeanDefinition
(
beanName
);
BeanDefinition
beanDefinition
=
beanFactory
.
getBeanDefinition
(
bean
);
if
(
beanDefinition
!=
null
&&
beanDefinition
.
isPrimary
())
{
if
(
beanDefinition
!=
null
&&
beanDefinition
.
isPrimary
())
{
if
(
primaryFound
)
{
primaryBeans
.
add
(
beanName
);
return
false
;
}
primaryFound
=
true
;
}
}
}
}
return
primary
Found
;
return
primary
Beans
;
}
}
private
static
class
BeanSearchSpec
{
private
static
class
BeanSearchSpec
{
...
@@ -288,8 +282,7 @@ public class OnBeanCondition extends SpringBootCondition implements
...
@@ -288,8 +282,7 @@ public class OnBeanCondition extends SpringBootCondition implements
return
"@"
+
ClassUtils
.
getShortName
(
this
.
annotationType
);
return
"@"
+
ClassUtils
.
getShortName
(
this
.
annotationType
);
}
}
@SuppressWarnings
({
"unchecked"
,
"rawtypes"
})
protected
void
collect
(
MultiValueMap
<
String
,
Object
>
attributes
,
String
key
,
private
void
collect
(
MultiValueMap
<
String
,
Object
>
attributes
,
String
key
,
List
<
String
>
destination
)
{
List
<
String
>
destination
)
{
List
<?>
values
=
attributes
.
get
(
key
);
List
<?>
values
=
attributes
.
get
(
key
);
if
(
values
!=
null
)
{
if
(
values
!=
null
)
{
...
@@ -388,18 +381,17 @@ public class OnBeanCondition extends SpringBootCondition implements
...
@@ -388,18 +381,17 @@ public class OnBeanCondition extends SpringBootCondition implements
super
(
context
,
metadata
,
annotationType
);
super
(
context
,
metadata
,
annotationType
);
}
}
@Override
protected
void
collect
(
MultiValueMap
<
String
,
Object
>
attributes
,
String
key
,
List
<
String
>
destination
)
{
super
.
collect
(
attributes
,
key
,
destination
);
destination
.
removeAll
(
Arrays
.
asList
(
""
,
Object
.
class
.
getName
()));
}
@Override
@Override
protected
void
validate
()
{
protected
void
validate
()
{
List
<
String
>
types
=
getTypes
();
Assert
.
isTrue
(
getTypes
().
size
()
==
1
,
annotationName
()
+
" annotations must "
ListIterator
<
String
>
it
=
types
.
listIterator
();
+
"specify only one type (got "
+
getTypes
()
+
")"
);
while
(
it
.
hasNext
())
{
String
value
=
it
.
next
();
if
(!
StringUtils
.
hasText
(
value
)
||
Object
.
class
.
getName
().
equals
(
value
))
{
it
.
remove
();
}
}
Assert
.
isTrue
(
types
.
size
()
==
1
,
annotationName
()
+
" annotations must "
+
"specify only one type (got "
+
types
+
")"
);
}
}
}
}
...
...
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnSingleCandidateTests.java
View file @
c4ddce6b
...
@@ -20,7 +20,6 @@ import org.junit.After;
...
@@ -20,7 +20,6 @@ import org.junit.After;
import
org.junit.Rule
;
import
org.junit.Rule
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.junit.rules.ExpectedException
;
import
org.junit.rules.ExpectedException
;
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.Configuration
;
import
org.springframework.context.annotation.Configuration
;
...
@@ -58,8 +57,7 @@ public class ConditionalOnSingleCandidateTests {
...
@@ -58,8 +57,7 @@ public class ConditionalOnSingleCandidateTests {
@Test
@Test
public
void
singleCandidateOneCandidate
()
{
public
void
singleCandidateOneCandidate
()
{
load
(
FooConfiguration
.
class
,
load
(
FooConfiguration
.
class
,
OnBeanSingleCandidateConfiguration
.
class
);
OnBeanSingleCandidateConfiguration
.
class
);
assertTrue
(
this
.
context
.
containsBean
(
"baz"
));
assertTrue
(
this
.
context
.
containsBean
(
"baz"
));
assertEquals
(
"foo"
,
this
.
context
.
getBean
(
"baz"
));
assertEquals
(
"foo"
,
this
.
context
.
getBean
(
"baz"
));
}
}
...
@@ -88,17 +86,19 @@ public class ConditionalOnSingleCandidateTests {
...
@@ -88,17 +86,19 @@ public class ConditionalOnSingleCandidateTests {
@Test
@Test
public
void
invalidAnnotationTwoTypes
()
{
public
void
invalidAnnotationTwoTypes
()
{
thrown
.
expect
(
IllegalStateException
.
class
);
this
.
thrown
.
expect
(
IllegalStateException
.
class
);
thrown
.
expectCause
(
isA
(
IllegalArgumentException
.
class
));
this
.
thrown
.
expectCause
(
isA
(
IllegalArgumentException
.
class
));
thrown
.
expectMessage
(
OnBeanSingleCandidateTwoTypesConfiguration
.
class
.
getName
());
this
.
thrown
.
expectMessage
(
OnBeanSingleCandidateTwoTypesConfiguration
.
class
.
getName
());
load
(
OnBeanSingleCandidateTwoTypesConfiguration
.
class
);
load
(
OnBeanSingleCandidateTwoTypesConfiguration
.
class
);
}
}
@Test
@Test
public
void
invalidAnnotationNoType
()
{
public
void
invalidAnnotationNoType
()
{
thrown
.
expect
(
IllegalStateException
.
class
);
this
.
thrown
.
expect
(
IllegalStateException
.
class
);
thrown
.
expectCause
(
isA
(
IllegalArgumentException
.
class
));
this
.
thrown
.
expectCause
(
isA
(
IllegalArgumentException
.
class
));
thrown
.
expectMessage
(
OnBeanSingleCandidateNoTypeConfiguration
.
class
.
getName
());
this
.
thrown
.
expectMessage
(
OnBeanSingleCandidateNoTypeConfiguration
.
class
.
getName
());
load
(
OnBeanSingleCandidateNoTypeConfiguration
.
class
);
load
(
OnBeanSingleCandidateNoTypeConfiguration
.
class
);
}
}
...
@@ -110,10 +110,12 @@ public class ConditionalOnSingleCandidateTests {
...
@@ -110,10 +110,12 @@ public class ConditionalOnSingleCandidateTests {
@Configuration
@Configuration
@ConditionalOnSingleCandidate
(
value
=
String
.
class
)
@ConditionalOnSingleCandidate
(
value
=
String
.
class
)
protected
static
class
OnBeanSingleCandidateConfiguration
{
protected
static
class
OnBeanSingleCandidateConfiguration
{
@Bean
@Bean
public
String
baz
(
String
s
)
{
public
String
baz
(
String
s
)
{
return
s
;
return
s
;
}
}
}
}
@Configuration
@Configuration
...
@@ -130,35 +132,43 @@ public class ConditionalOnSingleCandidateTests {
...
@@ -130,35 +132,43 @@ public class ConditionalOnSingleCandidateTests {
@Configuration
@Configuration
protected
static
class
FooConfiguration
{
protected
static
class
FooConfiguration
{
@Bean
@Bean
public
String
foo
()
{
public
String
foo
()
{
return
"foo"
;
return
"foo"
;
}
}
}
}
@Configuration
@Configuration
protected
static
class
FooPrimaryConfiguration
{
protected
static
class
FooPrimaryConfiguration
{
@Bean
@Bean
@Primary
@Primary
public
String
foo
()
{
public
String
foo
()
{
return
"foo"
;
return
"foo"
;
}
}
}
}
@Configuration
@Configuration
protected
static
class
BarConfiguration
{
protected
static
class
BarConfiguration
{
@Bean
@Bean
public
String
bar
()
{
public
String
bar
()
{
return
"bar"
;
return
"bar"
;
}
}
}
}
@Configuration
@Configuration
protected
static
class
BarPrimaryConfiguration
{
protected
static
class
BarPrimaryConfiguration
{
@Bean
@Bean
@Primary
@Primary
public
String
bar
()
{
public
String
bar
()
{
return
"bar"
;
return
"bar"
;
}
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment