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
c49b9bec
Commit
c49b9bec
authored
May 15, 2019
by
Phillip Webb
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.1.x'
Closes gh-16859
parents
a82b5266
ab15b8e2
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
109 additions
and
21 deletions
+109
-21
JavaBeanBinder.java
...ramework/boot/context/properties/bind/JavaBeanBinder.java
+35
-21
JavaBeanBinderTests.java
...ork/boot/context/properties/bind/JavaBeanBinderTests.java
+74
-0
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/JavaBeanBinder.java
View file @
c49b9bec
/*
/*
* Copyright 2012-201
8
the original author or authors.
* Copyright 2012-201
9
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.
...
@@ -97,8 +97,10 @@ class JavaBeanBinder implements BeanBinder {
...
@@ -97,8 +97,10 @@ class JavaBeanBinder implements BeanBinder {
/**
/**
* The bean being bound.
* The bean being bound.
*
* @param <T> the bean type
*/
*/
private
static
class
Bean
<
T
>
{
static
class
Bean
<
T
>
{
private
static
Bean
<?>
cached
;
private
static
Bean
<?>
cached
;
...
@@ -111,23 +113,36 @@ class JavaBeanBinder implements BeanBinder {
...
@@ -111,23 +113,36 @@ class JavaBeanBinder implements BeanBinder {
Bean
(
ResolvableType
type
,
Class
<?>
resolvedType
)
{
Bean
(
ResolvableType
type
,
Class
<?>
resolvedType
)
{
this
.
type
=
type
;
this
.
type
=
type
;
this
.
resolvedType
=
resolvedType
;
this
.
resolvedType
=
resolvedType
;
put
Properties
(
resolvedType
);
add
Properties
(
resolvedType
);
}
}
private
void
put
Properties
(
Class
<?>
type
)
{
private
void
add
Properties
(
Class
<?>
type
)
{
while
(
type
!=
null
&&
!
Object
.
class
.
equals
(
type
))
{
while
(
type
!=
null
&&
!
Object
.
class
.
equals
(
type
))
{
for
(
Method
method
:
type
.
getDeclaredMethods
())
{
Method
[]
declaredMethods
=
type
.
getDeclaredMethods
();
if
(
isCandidate
(
method
))
{
Field
[]
declaredFields
=
type
.
getDeclaredFields
();
addMethod
(
method
);
addProperties
(
declaredMethods
,
declaredFields
);
}
}
for
(
Field
field
:
type
.
getDeclaredFields
())
{
addField
(
field
);
}
type
=
type
.
getSuperclass
();
type
=
type
.
getSuperclass
();
}
}
}
}
protected
void
addProperties
(
Method
[]
declaredMethods
,
Field
[]
declaredFields
)
{
for
(
int
i
=
0
;
i
<
declaredMethods
.
length
;
i
++)
{
if
(!
isCandidate
(
declaredMethods
[
i
]))
{
declaredMethods
[
i
]
=
null
;
}
}
for
(
Method
method
:
declaredMethods
)
{
addMethodIfPossible
(
method
,
"get"
,
0
,
BeanProperty:
:
addGetter
);
}
for
(
Method
method
:
declaredMethods
)
{
addMethodIfPossible
(
method
,
"is"
,
0
,
BeanProperty:
:
addGetter
);
addMethodIfPossible
(
method
,
"set"
,
1
,
BeanProperty:
:
addSetter
);
}
for
(
Field
field
:
declaredFields
)
{
addField
(
field
);
}
}
private
boolean
isCandidate
(
Method
method
)
{
private
boolean
isCandidate
(
Method
method
)
{
int
modifiers
=
method
.
getModifiers
();
int
modifiers
=
method
.
getModifiers
();
return
Modifier
.
isPublic
(
modifiers
)
&&
!
Modifier
.
isAbstract
(
modifiers
)
return
Modifier
.
isPublic
(
modifiers
)
&&
!
Modifier
.
isAbstract
(
modifiers
)
...
@@ -136,15 +151,9 @@ class JavaBeanBinder implements BeanBinder {
...
@@ -136,15 +151,9 @@ class JavaBeanBinder implements BeanBinder {
&&
!
Class
.
class
.
equals
(
method
.
getDeclaringClass
());
&&
!
Class
.
class
.
equals
(
method
.
getDeclaringClass
());
}
}
private
void
addMethod
(
Method
method
)
{
addMethodIfPossible
(
method
,
"get"
,
0
,
BeanProperty:
:
addGetter
);
addMethodIfPossible
(
method
,
"is"
,
0
,
BeanProperty:
:
addGetter
);
addMethodIfPossible
(
method
,
"set"
,
1
,
BeanProperty:
:
addSetter
);
}
private
void
addMethodIfPossible
(
Method
method
,
String
prefix
,
int
parameterCount
,
private
void
addMethodIfPossible
(
Method
method
,
String
prefix
,
int
parameterCount
,
BiConsumer
<
BeanProperty
,
Method
>
consumer
)
{
BiConsumer
<
BeanProperty
,
Method
>
consumer
)
{
if
(
method
.
getParameterCount
()
==
parameterCount
if
(
method
!=
null
&&
method
.
getParameterCount
()
==
parameterCount
&&
method
.
getName
().
startsWith
(
prefix
)
&&
method
.
getName
().
startsWith
(
prefix
)
&&
method
.
getName
().
length
()
>
prefix
.
length
())
{
&&
method
.
getName
().
length
()
>
prefix
.
length
())
{
String
propertyName
=
Introspector
String
propertyName
=
Introspector
...
@@ -250,7 +259,7 @@ class JavaBeanBinder implements BeanBinder {
...
@@ -250,7 +259,7 @@ class JavaBeanBinder implements BeanBinder {
/**
/**
* A bean property being bound.
* A bean property being bound.
*/
*/
private
static
class
BeanProperty
{
static
class
BeanProperty
{
private
final
String
name
;
private
final
String
name
;
...
@@ -274,11 +283,16 @@ class JavaBeanBinder implements BeanBinder {
...
@@ -274,11 +283,16 @@ class JavaBeanBinder implements BeanBinder {
}
}
public
void
addSetter
(
Method
setter
)
{
public
void
addSetter
(
Method
setter
)
{
if
(
this
.
setter
==
null
)
{
if
(
this
.
setter
==
null
||
isBetterSetter
(
setter
)
)
{
this
.
setter
=
setter
;
this
.
setter
=
setter
;
}
}
}
}
private
boolean
isBetterSetter
(
Method
setter
)
{
return
this
.
getter
!=
null
&&
this
.
getter
.
getReturnType
().
equals
(
setter
.
getParameterTypes
()[
0
]);
}
public
void
addField
(
Field
field
)
{
public
void
addField
(
Field
field
)
{
if
(
this
.
field
==
null
)
{
if
(
this
.
field
==
null
)
{
this
.
field
=
field
;
this
.
field
=
field
;
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/JavaBeanBinderTests.java
View file @
c49b9bec
...
@@ -16,6 +16,8 @@
...
@@ -16,6 +16,8 @@
package
org
.
springframework
.
boot
.
context
.
properties
.
bind
;
package
org
.
springframework
.
boot
.
context
.
properties
.
bind
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
java.time.LocalDate
;
import
java.time.LocalDate
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collection
;
...
@@ -28,11 +30,14 @@ import java.util.Set;
...
@@ -28,11 +30,14 @@ import java.util.Set;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.springframework.boot.context.properties.bind.JavaBeanBinder.Bean
;
import
org.springframework.boot.context.properties.bind.JavaBeanBinder.BeanProperty
;
import
org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler
;
import
org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertyName
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertyName
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertySource
;
import
org.springframework.boot.context.properties.source.ConfigurationPropertySource
;
import
org.springframework.boot.context.properties.source.MockConfigurationPropertySource
;
import
org.springframework.boot.context.properties.source.MockConfigurationPropertySource
;
import
org.springframework.boot.convert.Delimiter
;
import
org.springframework.boot.convert.Delimiter
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.format.annotation.DateTimeFormat
;
import
org.springframework.format.annotation.DateTimeFormat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
...
@@ -44,6 +49,7 @@ import static org.assertj.core.api.Assertions.entry;
...
@@ -44,6 +49,7 @@ import static org.assertj.core.api.Assertions.entry;
*
*
* @author Phillip Webb
* @author Phillip Webb
* @author Madhura Bhave
* @author Madhura Bhave
* @author Andy Wilkinson
*/
*/
public
class
JavaBeanBinderTests
{
public
class
JavaBeanBinderTests
{
...
@@ -507,6 +513,56 @@ public class JavaBeanBinderTests {
...
@@ -507,6 +513,56 @@ public class JavaBeanBinderTests {
assertThat
(
bean
.
getBooleans
().
get
(
"b"
).
getValue
()).
isEqualTo
(
true
);
assertThat
(
bean
.
getBooleans
().
get
(
"b"
).
getValue
()).
isEqualTo
(
true
);
}
}
public
void
bindToClassWithOverloadedSetterShouldUseSetterThatMatchesField
()
{
// gh-16206
MockConfigurationPropertySource
source
=
new
MockConfigurationPropertySource
();
source
.
put
(
"foo.property"
,
"some string"
);
this
.
sources
.
add
(
source
);
PropertyWithOverloadedSetter
bean
=
this
.
binder
.
bind
(
"foo"
,
Bindable
.
of
(
PropertyWithOverloadedSetter
.
class
)).
get
();
assertThat
(
bean
.
getProperty
()).
isEqualTo
(
"some string"
);
}
@Test
public
void
beanProperiesPreferMatchingType
()
{
// gh-16206
ResolvableType
type
=
ResolvableType
.
forClass
(
PropertyWithOverloadedSetter
.
class
);
Bean
<
PropertyWithOverloadedSetter
>
bean
=
new
Bean
<
PropertyWithOverloadedSetter
>(
type
,
type
.
resolve
())
{
@Override
protected
void
addProperties
(
Method
[]
declaredMethods
,
Field
[]
declaredFields
)
{
// We override here because we need a specific order of the declared
// methods and the JVM doesn't give us one
int
intSetter
=
-
1
;
int
stringSetter
=
-
1
;
for
(
int
i
=
0
;
i
<
declaredMethods
.
length
;
i
++)
{
Method
method
=
declaredMethods
[
i
];
if
(
method
.
getName
().
equals
(
"setProperty"
))
{
if
(
method
.
getParameters
()[
0
].
getType
().
equals
(
int
.
class
))
{
intSetter
=
i
;
}
else
{
stringSetter
=
i
;
}
}
}
if
(
intSetter
>
stringSetter
)
{
Method
method
=
declaredMethods
[
intSetter
];
declaredMethods
[
intSetter
]
=
declaredMethods
[
stringSetter
];
declaredMethods
[
stringSetter
]
=
method
;
}
super
.
addProperties
(
declaredMethods
,
declaredFields
);
}
};
BeanProperty
property
=
bean
.
getProperties
().
get
(
"property"
);
PropertyWithOverloadedSetter
target
=
new
PropertyWithOverloadedSetter
();
property
.
setValue
(()
->
target
,
"some string"
);
}
public
static
class
ExampleValueBean
{
public
static
class
ExampleValueBean
{
private
int
intValue
;
private
int
intValue
;
...
@@ -957,4 +1013,22 @@ public class JavaBeanBinderTests {
...
@@ -957,4 +1013,22 @@ public class JavaBeanBinderTests {
}
}
public
static
class
PropertyWithOverloadedSetter
{
private
String
property
;
public
void
setProperty
(
int
property
)
{
this
.
property
=
String
.
valueOf
(
property
);
}
public
void
setProperty
(
String
property
)
{
this
.
property
=
property
;
}
public
String
getProperty
()
{
return
this
.
property
;
}
}
}
}
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