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
34420a87
Commit
34420a87
authored
May 05, 2016
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Allow @ConditionalOnProperty to be used as a meta-annotation
Closes gh-5819
parent
147956a7
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
138 additions
and
6 deletions
+138
-6
OnPropertyCondition.java
...ork/boot/autoconfigure/condition/OnPropertyCondition.java
+65
-5
ConditionalOnPropertyTests.java
...t/autoconfigure/condition/ConditionalOnPropertyTests.java
+73
-1
No files found.
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java
View file @
34420a87
/*
* Copyright 2012-201
4
the original author or authors.
* Copyright 2012-201
6
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.
...
...
@@ -17,8 +17,10 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
org.springframework.boot.bind.RelaxedPropertyResolver
;
import
org.springframework.context.annotation.Condition
;
...
...
@@ -27,6 +29,7 @@ import org.springframework.core.annotation.AnnotationAttributes;
import
org.springframework.core.env.PropertyResolver
;
import
org.springframework.core.type.AnnotatedTypeMetadata
;
import
org.springframework.util.Assert
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.util.StringUtils
;
/**
...
...
@@ -35,6 +38,7 @@ import org.springframework.util.StringUtils;
* @author Maciej Walkowiak
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
* @since 1.1.0
* @see ConditionalOnProperty
*/
...
...
@@ -43,10 +47,57 @@ class OnPropertyCondition extends SpringBootCondition {
@Override
public
ConditionOutcome
getMatchOutcome
(
ConditionContext
context
,
AnnotatedTypeMetadata
metadata
)
{
List
<
AnnotationAttributes
>
allAnnotationAttributes
=
annotationAttributesFromMultiValueMap
(
metadata
.
getAllAnnotationAttributes
(
ConditionalOnProperty
.
class
.
getName
()));
List
<
ConditionOutcome
>
noMatchOutcomes
=
findNoMatchOutcomes
(
allAnnotationAttributes
,
context
.
getEnvironment
());
if
(
noMatchOutcomes
.
isEmpty
())
{
return
ConditionOutcome
.
match
();
}
return
ConditionOutcome
.
noMatch
(
getCompositeMessage
(
noMatchOutcomes
));
}
private
List
<
AnnotationAttributes
>
annotationAttributesFromMultiValueMap
(
MultiValueMap
<
String
,
Object
>
multiValueMap
)
{
List
<
Map
<
String
,
Object
>>
maps
=
new
ArrayList
<
Map
<
String
,
Object
>>();
for
(
Entry
<
String
,
List
<
Object
>>
entry
:
multiValueMap
.
entrySet
())
{
for
(
int
i
=
0
;
i
<
entry
.
getValue
().
size
();
i
++)
{
Map
<
String
,
Object
>
map
;
if
(
i
<
maps
.
size
())
{
map
=
maps
.
get
(
i
);
}
else
{
map
=
new
HashMap
<
String
,
Object
>();
maps
.
add
(
map
);
}
map
.
put
(
entry
.
getKey
(),
entry
.
getValue
().
get
(
i
));
}
}
List
<
AnnotationAttributes
>
annotationAttributes
=
new
ArrayList
<
AnnotationAttributes
>(
maps
.
size
());
for
(
Map
<
String
,
Object
>
map
:
maps
)
{
annotationAttributes
.
add
(
AnnotationAttributes
.
fromMap
(
map
));
}
return
annotationAttributes
;
}
AnnotationAttributes
annotationAttributes
=
AnnotationAttributes
.
fromMap
(
metadata
.
getAnnotationAttributes
(
ConditionalOnProperty
.
class
.
getName
()));
private
List
<
ConditionOutcome
>
findNoMatchOutcomes
(
List
<
AnnotationAttributes
>
allAnnotationAttributes
,
PropertyResolver
resolver
)
{
List
<
ConditionOutcome
>
noMatchOutcomes
=
new
ArrayList
<
ConditionOutcome
>(
allAnnotationAttributes
.
size
());
for
(
AnnotationAttributes
annotationAttributes
:
allAnnotationAttributes
)
{
ConditionOutcome
outcome
=
determineOutcome
(
annotationAttributes
,
resolver
);
if
(!
outcome
.
isMatch
())
{
noMatchOutcomes
.
add
(
outcome
);
}
}
return
noMatchOutcomes
;
}
private
ConditionOutcome
determineOutcome
(
AnnotationAttributes
annotationAttributes
,
PropertyResolver
resolver
)
{
String
prefix
=
annotationAttributes
.
getString
(
"prefix"
).
trim
();
if
(
StringUtils
.
hasText
(
prefix
)
&&
!
prefix
.
endsWith
(
"."
))
{
prefix
=
prefix
+
"."
;
...
...
@@ -56,7 +107,6 @@ class OnPropertyCondition extends SpringBootCondition {
boolean
relaxedNames
=
annotationAttributes
.
getBoolean
(
"relaxedNames"
);
boolean
matchIfMissing
=
annotationAttributes
.
getBoolean
(
"matchIfMissing"
);
PropertyResolver
resolver
=
context
.
getEnvironment
();
if
(
relaxedNames
)
{
resolver
=
new
RelaxedPropertyResolver
(
resolver
,
prefix
);
}
...
...
@@ -91,7 +141,6 @@ class OnPropertyCondition extends SpringBootCondition {
message
.
append
(
"expected '"
).
append
(
expected
).
append
(
"' for properties "
)
.
append
(
expandNames
(
prefix
,
nonMatchingProperties
));
}
return
ConditionOutcome
.
noMatch
(
message
.
toString
());
}
...
...
@@ -122,4 +171,15 @@ class OnPropertyCondition extends SpringBootCondition {
return
expanded
.
toString
();
}
private
String
getCompositeMessage
(
List
<
ConditionOutcome
>
noMatchOutcomes
)
{
StringBuilder
message
=
new
StringBuilder
();
for
(
ConditionOutcome
noMatchOutcome
:
noMatchOutcomes
)
{
if
(
message
.
length
()
>
0
)
{
message
.
append
(
". "
);
}
message
.
append
(
noMatchOutcome
.
getMessage
().
trim
());
}
return
message
.
toString
();
}
}
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnPropertyTests.java
View file @
34420a87
/*
* Copyright 2012-201
4
the original author or authors.
* Copyright 2012-201
6
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,6 +16,11 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
org.junit.After
;
import
org.junit.Rule
;
import
org.junit.Test
;
...
...
@@ -37,6 +42,7 @@ import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage;
* @author Maciej Walkowiak
* @author Stephane Nicoll
* @author Phillip Webb
* @author Andy Wilkinson
*/
public
class
ConditionalOnPropertyTests
{
...
...
@@ -227,6 +233,44 @@ public class ConditionalOnPropertyTests {
load
(
NameAndValueAttribute
.
class
,
"some.property"
);
}
@Test
public
void
metaAnnotationConditionMatchesWhenPropertyIsSet
()
throws
Exception
{
load
(
MetaAnnotation
.
class
,
"my.feature.enabled=true"
);
assertTrue
(
this
.
context
.
containsBean
(
"foo"
));
}
@Test
public
void
metaAnnotationConditionDoesNotMatchWhenPropertyIsNotSet
()
throws
Exception
{
load
(
MetaAnnotation
.
class
);
assertFalse
(
this
.
context
.
containsBean
(
"foo"
));
}
@Test
public
void
metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyDirectPropertyIsSet
()
{
load
(
MetaAnnotationAndDirectAnnotation
.
class
,
"my.other.feature.enabled=true"
);
assertFalse
(
this
.
context
.
containsBean
(
"foo"
));
}
@Test
public
void
metaAndDirectAnnotationConditionDoesNotMatchWhenOnlyMetaPropertyIsSet
()
{
load
(
MetaAnnotationAndDirectAnnotation
.
class
,
"my.feature.enabled=true"
);
assertFalse
(
this
.
context
.
containsBean
(
"foo"
));
}
@Test
public
void
metaAndDirectAnnotationConditionDoesNotMatchWhenNeitherPropertyIsSet
()
{
load
(
MetaAnnotationAndDirectAnnotation
.
class
);
assertFalse
(
this
.
context
.
containsBean
(
"foo"
));
}
@Test
public
void
metaAndDirectAnnotationConditionMatchesWhenBothPropertiesAreSet
()
{
load
(
MetaAnnotationAndDirectAnnotation
.
class
,
"my.feature.enabled=true"
,
"my.other.feature.enabled=true"
);
assertTrue
(
this
.
context
.
containsBean
(
"foo"
));
}
private
void
load
(
Class
<?>
config
,
String
...
environment
)
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
EnvironmentTestUtils
.
addEnvironment
(
this
.
context
,
environment
);
...
...
@@ -390,4 +434,32 @@ public class ConditionalOnPropertyTests {
}
}
@ConditionalOnMyFeature
protected
static
class
MetaAnnotation
{
@Bean
public
String
foo
()
{
return
"foo"
;
}
}
@ConditionalOnMyFeature
@ConditionalOnProperty
(
prefix
=
"my.other.feature"
,
name
=
"enabled"
,
havingValue
=
"true"
,
matchIfMissing
=
false
)
protected
static
class
MetaAnnotationAndDirectAnnotation
{
@Bean
public
String
foo
()
{
return
"foo"
;
}
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
({
ElementType
.
TYPE
,
ElementType
.
METHOD
})
@ConditionalOnProperty
(
prefix
=
"my.feature"
,
name
=
"enabled"
,
havingValue
=
"true"
,
matchIfMissing
=
false
)
public
@interface
ConditionalOnMyFeature
{
}
}
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