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
761bcffc
Commit
761bcffc
authored
Feb 07, 2018
by
Madhura Bhave
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Consider generic information on @Bean method for bind
Fixes gh-11931
parent
dd3bcc56
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
77 additions
and
14 deletions
+77
-14
ConfigurationBeanFactoryMetadata.java
.../context/properties/ConfigurationBeanFactoryMetadata.java
+3
-0
ConfigurationPropertiesBinder.java
...oot/context/properties/ConfigurationPropertiesBinder.java
+4
-2
ConfigurationPropertiesBindingPostProcessor.java
...operties/ConfigurationPropertiesBindingPostProcessor.java
+8
-1
JavaBeanBinder.java
...ramework/boot/context/properties/bind/JavaBeanBinder.java
+18
-9
ConfigurationPropertiesBinderBuilderTests.java
...properties/ConfigurationPropertiesBinderBuilderTests.java
+2
-1
ConfigurationPropertiesBinderTests.java
...ontext/properties/ConfigurationPropertiesBinderTests.java
+2
-1
ConfigurationPropertiesBindingPostProcessorTests.java
...ies/ConfigurationPropertiesBindingPostProcessorTests.java
+40
-0
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata.java
View file @
761bcffc
...
...
@@ -82,6 +82,9 @@ public class ConfigurationBeanFactoryMetadata implements BeanFactoryPostProcesso
FactoryMetadata
metadata
=
this
.
beansFactoryMetadata
.
get
(
beanName
);
Class
<?>
factoryType
=
this
.
beanFactory
.
getType
(
metadata
.
getBean
());
String
factoryMethod
=
metadata
.
getMethod
();
if
(
ClassUtils
.
isCglibProxyClass
(
factoryType
))
{
factoryType
=
factoryType
.
getSuperclass
();
}
ReflectionUtils
.
doWithMethods
(
factoryType
,
(
method
)
->
{
if
(
method
.
getName
().
equals
(
factoryMethod
))
{
found
.
compareAndSet
(
null
,
method
);
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinder.java
View file @
761bcffc
...
...
@@ -26,6 +26,7 @@ import org.springframework.boot.context.properties.bind.validation.ValidationBin
import
org.springframework.boot.context.properties.source.ConfigurationPropertySource
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertySources
;
import
org.springframework.boot.context.properties.source.UnboundElementsSourceFilter
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.convert.ConversionService
;
import
org.springframework.core.env.PropertySource
;
import
org.springframework.util.Assert
;
...
...
@@ -69,12 +70,13 @@ class ConfigurationPropertiesBinder {
* specified {@code annotation}.
* @param target the target to bind the configuration property sources to
* @param annotation the binding configuration
* @param targetType the resolvable type for the target
* @throws ConfigurationPropertiesBindingException if the binding failed
*/
void
bind
(
Object
target
,
ConfigurationProperties
annotation
)
{
void
bind
(
Object
target
,
ConfigurationProperties
annotation
,
ResolvableType
targetType
)
{
Validator
validator
=
determineValidator
(
target
);
BindHandler
handler
=
getBindHandler
(
annotation
,
validator
);
Bindable
<?>
bindable
=
Bindable
.
of
Instanc
e
(
target
);
Bindable
<?>
bindable
=
Bindable
.
of
(
targetType
).
withExistingValu
e
(
target
);
try
{
this
.
binder
.
bind
(
annotation
.
prefix
(),
bindable
,
handler
);
}
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessor.java
View file @
761bcffc
...
...
@@ -16,6 +16,7 @@
package
org
.
springframework
.
boot
.
context
.
properties
;
import
java.lang.reflect.Method
;
import
java.util.Map
;
import
org.apache.commons.logging.Log
;
...
...
@@ -34,6 +35,7 @@ import org.springframework.context.EnvironmentAware;
import
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.PriorityOrdered
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.core.env.ConfigurableEnvironment
;
import
org.springframework.core.env.Environment
;
...
...
@@ -164,7 +166,12 @@ public class ConfigurationPropertiesBindingPostProcessor
ConfigurationProperties
annotation
=
getAnnotation
(
bean
,
beanName
);
if
(
annotation
!=
null
)
{
try
{
getBinder
().
bind
(
bean
,
annotation
);
ResolvableType
type
=
ResolvableType
.
forClass
(
bean
.
getClass
());
Method
factoryMethod
=
this
.
beans
.
findFactoryMethod
(
beanName
);
if
(
factoryMethod
!=
null
)
{
type
=
ResolvableType
.
forMethodReturnType
(
factoryMethod
);
}
getBinder
().
bind
(
bean
,
annotation
,
type
);
}
catch
(
ConfigurationPropertiesBindingException
ex
)
{
throw
new
BeanCreationException
(
beanName
,
ex
.
getMessage
(),
ex
.
getCause
());
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java
View file @
761bcffc
...
...
@@ -28,6 +28,7 @@ import java.util.function.Supplier;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertyName
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertyState
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.ResolvableType
;
/**
...
...
@@ -91,9 +92,12 @@ class JavaBeanBinder implements BeanBinder {
private
final
Class
<?>
type
;
private
final
ResolvableType
resolvableType
;
private
final
Map
<
String
,
BeanProperty
>
properties
=
new
LinkedHashMap
<>();
Bean
(
Class
<?>
type
)
{
Bean
(
ResolvableType
resolvableType
,
Class
<?>
type
)
{
this
.
resolvableType
=
resolvableType
;
this
.
type
=
type
;
putProperties
(
type
);
}
...
...
@@ -123,17 +127,17 @@ class JavaBeanBinder implements BeanBinder {
int
parameterCount
=
method
.
getParameterCount
();
if
(
name
.
startsWith
(
"get"
)
&&
parameterCount
==
0
)
{
name
=
Introspector
.
decapitalize
(
name
.
substring
(
3
));
this
.
properties
.
computeIfAbsent
(
name
,
BeanProperty:
:
new
)
this
.
properties
.
computeIfAbsent
(
name
,
n
->
new
BeanProperty
(
n
,
this
.
resolvableType
)
)
.
addGetter
(
method
);
}
else
if
(
name
.
startsWith
(
"is"
)
&&
parameterCount
==
0
)
{
name
=
Introspector
.
decapitalize
(
name
.
substring
(
2
));
this
.
properties
.
computeIfAbsent
(
name
,
BeanProperty:
:
new
)
this
.
properties
.
computeIfAbsent
(
name
,
n
->
new
BeanProperty
(
n
,
this
.
resolvableType
)
)
.
addGetter
(
method
);
}
else
if
(
name
.
startsWith
(
"set"
)
&&
parameterCount
==
1
)
{
name
=
Introspector
.
decapitalize
(
name
.
substring
(
3
));
this
.
properties
.
computeIfAbsent
(
name
,
BeanProperty:
:
new
)
this
.
properties
.
computeIfAbsent
(
name
,
n
->
new
BeanProperty
(
n
,
this
.
resolvableType
)
)
.
addSetter
(
method
);
}
}
...
...
@@ -169,7 +173,7 @@ class JavaBeanBinder implements BeanBinder {
@SuppressWarnings
(
"unchecked"
)
public
static
<
T
>
Bean
<
T
>
get
(
Bindable
<
T
>
bindable
,
boolean
canCallGetValue
)
{
Class
<?>
type
=
bindable
.
getType
().
resolve
();
Class
<?>
type
=
bindable
.
getType
().
resolve
(
Object
.
class
);
Supplier
<
T
>
value
=
bindable
.
getValue
();
T
instance
=
null
;
if
(
canCallGetValue
&&
value
!=
null
)
{
...
...
@@ -181,7 +185,7 @@ class JavaBeanBinder implements BeanBinder {
}
Bean
<?>
bean
=
Bean
.
cached
;
if
(
bean
==
null
||
!
type
.
equals
(
bean
.
getType
()))
{
bean
=
new
Bean
<>(
type
);
bean
=
new
Bean
<>(
bindable
.
getType
(),
type
);
cached
=
bean
;
}
return
(
Bean
<
T
>)
bean
;
...
...
@@ -229,14 +233,17 @@ class JavaBeanBinder implements BeanBinder {
private
final
String
name
;
private
final
ResolvableType
declaringClassType
;
private
Method
getter
;
private
Method
setter
;
private
Field
field
;
BeanProperty
(
String
name
)
{
BeanProperty
(
String
name
,
ResolvableType
declaringClassType
)
{
this
.
name
=
BeanPropertyName
.
toDashedForm
(
name
);
this
.
declaringClassType
=
declaringClassType
;
}
public
void
addGetter
(
Method
getter
)
{
...
...
@@ -263,9 +270,11 @@ class JavaBeanBinder implements BeanBinder {
public
ResolvableType
getType
()
{
if
(
this
.
setter
!=
null
)
{
return
ResolvableType
.
forMethodParameter
(
this
.
setter
,
0
);
MethodParameter
methodParameter
=
new
MethodParameter
(
this
.
setter
,
0
);
return
ResolvableType
.
forMethodParameter
(
methodParameter
,
this
.
declaringClassType
);
}
return
ResolvableType
.
forMethodReturnType
(
this
.
getter
);
MethodParameter
methodParameter
=
new
MethodParameter
(
this
.
getter
,
-
1
);
return
ResolvableType
.
forMethodParameter
(
methodParameter
,
this
.
declaringClassType
);
}
public
Annotation
[]
getAnnotations
()
{
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinderBuilderTests.java
View file @
761bcffc
...
...
@@ -25,6 +25,7 @@ import org.junit.Test;
import
org.springframework.boot.context.properties.bind.validation.BindValidationException
;
import
org.springframework.boot.context.properties.bind.validation.ValidationErrors
;
import
org.springframework.context.support.StaticApplicationContext
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.core.convert.support.DefaultConversionService
;
import
org.springframework.mock.env.MockEnvironment
;
...
...
@@ -128,7 +129,7 @@ public class ConfigurationPropertiesBinderBuilderTests {
private
void
bind
(
ConfigurationPropertiesBinder
binder
,
Object
target
)
{
binder
.
bind
(
target
,
AnnotationUtils
.
findAnnotation
(
target
.
getClass
(),
ConfigurationProperties
.
class
));
ConfigurationProperties
.
class
)
,
ResolvableType
.
forType
(
target
.
getClass
())
);
}
@ConfigurationProperties
(
prefix
=
"test"
)
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBinderTests.java
View file @
761bcffc
...
...
@@ -25,6 +25,7 @@ import org.junit.Test;
import
org.springframework.boot.context.properties.bind.BindException
;
import
org.springframework.boot.context.properties.bind.validation.BindValidationException
;
import
org.springframework.boot.context.properties.bind.validation.ValidationErrors
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.core.env.MapPropertySource
;
import
org.springframework.core.env.MutablePropertySources
;
...
...
@@ -269,7 +270,7 @@ public class ConfigurationPropertiesBinderTests {
private
void
bind
(
ConfigurationPropertiesBinder
binder
,
Object
target
)
{
binder
.
bind
(
target
,
AnnotationUtils
.
findAnnotation
(
target
.
getClass
(),
ConfigurationProperties
.
class
));
ConfigurationProperties
.
class
)
,
ResolvableType
.
forType
(
target
.
getClass
())
);
}
@ConfigurationProperties
(
value
=
"person"
,
ignoreUnknownFields
=
false
)
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesBindingPostProcessorTests.java
View file @
761bcffc
...
...
@@ -287,6 +287,20 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
assertThat
(
foo
.
getFoos
().
get
(
"1"
)).
isNotNull
();
}
@Test
public
void
bindToBeanWithGenerics
()
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
MutablePropertySources
sources
=
this
.
context
.
getEnvironment
()
.
getPropertySources
();
Map
<
String
,
Object
>
source
=
new
LinkedHashMap
<>();
source
.
put
(
"foo.bar"
,
"hello"
);
sources
.
addFirst
(
new
MapPropertySource
(
"test-source"
,
source
));
this
.
context
.
register
(
GenericConfiguration
.
class
);
this
.
context
.
refresh
();
AGenericClass
foo
=
this
.
context
.
getBean
(
AGenericClass
.
class
);
assertThat
(
foo
.
getBar
()).
isNotNull
();
}
private
void
prepareConverterContext
(
Class
<?>...
config
)
{
this
.
context
=
new
AnnotationConfigApplicationContext
();
MutablePropertySources
sources
=
this
.
context
.
getEnvironment
()
...
...
@@ -645,4 +659,30 @@ public class ConfigurationPropertiesBindingPostProcessorTests {
}
@Configuration
@EnableConfigurationProperties
static
class
GenericConfiguration
{
@Bean
@ConfigurationProperties
(
"foo"
)
public
AGenericClass
<
String
>
aBeanToBind
()
{
return
new
AGenericClass
<>();
}
}
static
class
AGenericClass
<
T
>
{
private
T
bar
;
public
T
getBar
()
{
return
this
.
bar
;
}
public
void
setBar
(
T
bar
)
{
this
.
bar
=
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