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
e3b839a4
Commit
e3b839a4
authored
Jul 14, 2020
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '2.3.x'
Closes gh-22326
parents
2643c60c
196d2053
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
209 additions
and
107 deletions
+209
-107
ConfigurationPropertiesBeanDefinitionValidator.java
...rties/ConfigurationPropertiesBeanDefinitionValidator.java
+0
-91
EnableConfigurationPropertiesRegistrar.java
...xt/properties/EnableConfigurationPropertiesRegistrar.java
+0
-1
NotConstructorBoundInjectionFailureAnalyzer.java
...operties/NotConstructorBoundInjectionFailureAnalyzer.java
+83
-0
spring.factories
.../spring-boot/src/main/resources/META-INF/spring.factories
+1
-0
ConfigurationPropertiesTests.java
...boot/context/properties/ConfigurationPropertiesTests.java
+0
-15
NotConstructorBoundInjectionFailureAnalyzerTests.java
...ies/NotConstructorBoundInjectionFailureAnalyzerTests.java
+125
-0
No files found.
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/ConfigurationPropertiesBeanDefinitionValidator.java
deleted
100644 → 0
View file @
2643c60c
/*
* Copyright 2012-2019 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
context
.
properties
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.BeanCreationException
;
import
org.springframework.beans.factory.CannotLoadBeanClassException
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.BeanFactoryPostProcessor
;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.GenericBeanDefinition
;
import
org.springframework.boot.context.properties.ConfigurationPropertiesBean.BindMethod
;
import
org.springframework.core.Ordered
;
import
org.springframework.util.Assert
;
/**
* {@link BeanFactoryPostProcessor} to validate that regular bean definitions aren't
* creating {@link ConstructorBinding} beans.
*
* @author Phillip Webb
*/
class
ConfigurationPropertiesBeanDefinitionValidator
implements
BeanFactoryPostProcessor
,
Ordered
{
private
static
final
String
BEAN_NAME
=
ConfigurationPropertiesBeanDefinitionValidator
.
class
.
getName
();
@Override
public
void
postProcessBeanFactory
(
ConfigurableListableBeanFactory
beanFactory
)
throws
BeansException
{
for
(
String
beanName
:
beanFactory
.
getBeanDefinitionNames
())
{
if
(!(
beanFactory
.
containsSingleton
(
beanName
)
||
isValueObjectBeanDefinition
(
beanFactory
,
beanName
)))
{
validate
(
beanFactory
,
beanName
);
}
}
}
private
boolean
isValueObjectBeanDefinition
(
ConfigurableListableBeanFactory
beanFactory
,
String
beanName
)
{
BeanDefinition
definition
=
beanFactory
.
getBeanDefinition
(
beanName
);
return
(
definition
instanceof
ConfigurationPropertiesValueObjectBeanDefinition
);
}
@Override
public
int
getOrder
()
{
return
Ordered
.
LOWEST_PRECEDENCE
;
}
private
void
validate
(
ConfigurableListableBeanFactory
beanFactory
,
String
beanName
)
{
try
{
Class
<?>
beanClass
=
beanFactory
.
getType
(
beanName
,
false
);
if
(
beanClass
!=
null
&&
BindMethod
.
forType
(
beanClass
)
==
BindMethod
.
VALUE_OBJECT
)
{
throw
new
BeanCreationException
(
beanName
,
"@EnableConfigurationProperties or @ConfigurationPropertiesScan must be used to add "
+
"@ConstructorBinding type "
+
beanClass
.
getName
());
}
}
catch
(
CannotLoadBeanClassException
ex
)
{
// Ignore
}
}
/**
* Register a {@link ConfigurationPropertiesBeanDefinitionValidator} bean if one is
* not already registered.
* @param registry the bean definition registry
*/
static
void
register
(
BeanDefinitionRegistry
registry
)
{
Assert
.
notNull
(
registry
,
"Registry must not be null"
);
if
(!
registry
.
containsBeanDefinition
(
BEAN_NAME
))
{
GenericBeanDefinition
definition
=
new
GenericBeanDefinition
();
definition
.
setBeanClass
(
ConfigurationPropertiesBeanDefinitionValidator
.
class
);
definition
.
setRole
(
BeanDefinition
.
ROLE_INFRASTRUCTURE
);
registry
.
registerBeanDefinition
(
BEAN_NAME
,
definition
);
}
ConfigurationPropertiesBinder
.
register
(
registry
);
}
}
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/EnableConfigurationPropertiesRegistrar.java
View file @
e3b839a4
...
@@ -50,7 +50,6 @@ class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegi
...
@@ -50,7 +50,6 @@ class EnableConfigurationPropertiesRegistrar implements ImportBeanDefinitionRegi
static
void
registerInfrastructureBeans
(
BeanDefinitionRegistry
registry
)
{
static
void
registerInfrastructureBeans
(
BeanDefinitionRegistry
registry
)
{
ConfigurationPropertiesBindingPostProcessor
.
register
(
registry
);
ConfigurationPropertiesBindingPostProcessor
.
register
(
registry
);
BoundConfigurationProperties
.
register
(
registry
);
BoundConfigurationProperties
.
register
(
registry
);
ConfigurationPropertiesBeanDefinitionValidator
.
register
(
registry
);
ConfigurationBeanFactoryMetadata
.
register
(
registry
);
ConfigurationBeanFactoryMetadata
.
register
(
registry
);
}
}
...
...
spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/NotConstructorBoundInjectionFailureAnalyzer.java
0 → 100644
View file @
e3b839a4
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
context
.
properties
;
import
java.lang.reflect.Constructor
;
import
org.springframework.beans.factory.InjectionPoint
;
import
org.springframework.beans.factory.NoSuchBeanDefinitionException
;
import
org.springframework.beans.factory.UnsatisfiedDependencyException
;
import
org.springframework.boot.context.properties.ConfigurationPropertiesBean.BindMethod
;
import
org.springframework.boot.diagnostics.FailureAnalysis
;
import
org.springframework.boot.diagnostics.analyzer.AbstractInjectionFailureAnalyzer
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.annotation.MergedAnnotation
;
import
org.springframework.core.annotation.MergedAnnotations
;
/**
* An {@AbstractInjectionFailureAnalyzer} for
* {@link ConfigurationProperties @ConfigurationProperties} that are intended to use
* {@link ConstructorBinding constructor binding} but did not.
*
* @author Andy Wilkinson
*/
class
NotConstructorBoundInjectionFailureAnalyzer
extends
AbstractInjectionFailureAnalyzer
<
NoSuchBeanDefinitionException
>
implements
Ordered
{
@Override
public
int
getOrder
()
{
return
0
;
}
@Override
protected
FailureAnalysis
analyze
(
Throwable
rootFailure
,
NoSuchBeanDefinitionException
cause
,
String
description
)
{
InjectionPoint
injectionPoint
=
findInjectionPoint
(
rootFailure
);
if
(
isConstructorBindingConfigurationProperties
(
injectionPoint
))
{
String
simpleName
=
injectionPoint
.
getMember
().
getDeclaringClass
().
getSimpleName
();
String
action
=
String
.
format
(
"Update your configuration so that "
+
simpleName
+
" is defined via @"
+
ConfigurationPropertiesScan
.
class
.
getSimpleName
()
+
" or @"
+
EnableConfigurationProperties
.
class
.
getSimpleName
()
+
"."
,
simpleName
);
return
new
FailureAnalysis
(
simpleName
+
" is annotated with @"
+
ConstructorBinding
.
class
.
getSimpleName
()
+
" but it is defined as a regular bean which caused dependency injection to fail."
,
action
,
cause
);
}
return
null
;
}
private
boolean
isConstructorBindingConfigurationProperties
(
InjectionPoint
injectionPoint
)
{
if
(
injectionPoint
!=
null
&&
injectionPoint
.
getMember
()
instanceof
Constructor
)
{
Constructor
<?>
constructor
=
(
Constructor
<?>)
injectionPoint
.
getMember
();
Class
<?>
declaringClass
=
constructor
.
getDeclaringClass
();
MergedAnnotation
<
ConfigurationProperties
>
configurationProperties
=
MergedAnnotations
.
from
(
declaringClass
)
.
get
(
ConfigurationProperties
.
class
);
return
configurationProperties
.
isPresent
()
&&
BindMethod
.
forType
(
constructor
.
getDeclaringClass
())
==
BindMethod
.
VALUE_OBJECT
;
}
return
false
;
}
private
InjectionPoint
findInjectionPoint
(
Throwable
failure
)
{
UnsatisfiedDependencyException
unsatisfiedDependencyException
=
findCause
(
failure
,
UnsatisfiedDependencyException
.
class
);
if
(
unsatisfiedDependencyException
==
null
)
{
return
null
;
}
return
unsatisfiedDependencyException
.
getInjectionPoint
();
}
}
spring-boot-project/spring-boot/src/main/resources/META-INF/spring.factories
View file @
e3b839a4
...
@@ -41,6 +41,7 @@ org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
...
@@ -41,6 +41,7 @@ org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor
# Failure Analyzers
# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.context.properties.NotConstructorBoundInjectionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/ConfigurationPropertiesTests.java
View file @
e3b839a4
...
@@ -63,7 +63,6 @@ import org.springframework.boot.testsupport.system.OutputCaptureExtension;
...
@@ -63,7 +63,6 @@ import org.springframework.boot.testsupport.system.OutputCaptureExtension;
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
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.context.annotation.ImportResource
;
import
org.springframework.context.annotation.ImportResource
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.context.annotation.Scope
;
import
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
;
import
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
;
...
@@ -783,13 +782,6 @@ class ConfigurationPropertiesTests {
...
@@ -783,13 +782,6 @@ class ConfigurationPropertiesTests {
assertThat
(
bean
.
getPeriod
()).
isEqualTo
(
Period
.
ofYears
(
14
));
assertThat
(
bean
.
getPeriod
()).
isEqualTo
(
Period
.
ofYears
(
14
));
}
}
@Test
// gh-17831
void
loadWhenBindingConstructorParametersViaImportShouldThrowException
()
{
assertThatExceptionOfType
(
BeanCreationException
.
class
)
.
isThrownBy
(()
->
load
(
ImportConstructorParameterPropertiesConfiguration
.
class
))
.
withMessageContaining
(
"@EnableConfigurationProperties or @ConfigurationPropertiesScan must be used"
);
}
@Test
@Test
void
loadWhenBindingToConstructorParametersWithDefaultValuesShouldBind
()
{
void
loadWhenBindingToConstructorParametersWithDefaultValuesShouldBind
()
{
load
(
ConstructorParameterConfiguration
.
class
);
load
(
ConstructorParameterConfiguration
.
class
);
...
@@ -1996,13 +1988,6 @@ class ConfigurationPropertiesTests {
...
@@ -1996,13 +1988,6 @@ class ConfigurationPropertiesTests {
}
}
@Configuration
(
proxyBeanMethods
=
false
)
@EnableConfigurationProperties
@Import
(
ConstructorParameterProperties
.
class
)
static
class
ImportConstructorParameterPropertiesConfiguration
{
}
@ConstructorBinding
@ConstructorBinding
@ConfigurationProperties
(
prefix
=
"test"
)
@ConfigurationProperties
(
prefix
=
"test"
)
@Validated
@Validated
...
...
spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/NotConstructorBoundInjectionFailureAnalyzerTests.java
0 → 100644
View file @
e3b839a4
/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
context
.
properties
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.beans.FatalBeanException
;
import
org.springframework.boot.diagnostics.FailureAnalysis
;
import
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
/**
* Tests for {@link NotConstructorBoundInjectionFailureAnalyzer}.
*
* @author Andy Wilkinson
*/
class
NotConstructorBoundInjectionFailureAnalyzerTests
{
private
final
NotConstructorBoundInjectionFailureAnalyzer
analyzer
=
new
NotConstructorBoundInjectionFailureAnalyzer
();
@Test
void
failureAnalysisForConfigurationPropertiesThatShouldHaveBeenConstructorBound
()
{
FailureAnalysis
analysis
=
analyzeFailure
(
createFailure
(
ShouldHaveUsedConstructorBindingPropertiesConfiguration
.
class
));
assertThat
(
analysis
.
getDescription
()).
isEqualTo
(
ConstructorBoundProperties
.
class
.
getSimpleName
()
+
" is annotated with @"
+
ConstructorBinding
.
class
.
getSimpleName
()
+
" but it is defined as a regular bean which caused dependency injection to fail."
);
assertThat
(
analysis
.
getAction
())
.
isEqualTo
(
"Update your configuration so that "
+
ConstructorBoundProperties
.
class
.
getSimpleName
()
+
" is defined via @"
+
ConfigurationPropertiesScan
.
class
.
getSimpleName
()
+
" or @"
+
EnableConfigurationProperties
.
class
.
getSimpleName
()
+
"."
);
}
@Test
void
failureAnaylsisForNonConstructorBoundProperties
()
{
FailureAnalysis
analysis
=
analyzeFailure
(
createFailure
(
JavaBeanBoundPropertiesConfiguration
.
class
));
assertThat
(
analysis
).
isNull
();
}
private
FatalBeanException
createFailure
(
Class
<?>
config
)
{
try
(
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
())
{
context
.
register
(
config
);
context
.
refresh
();
return
null
;
}
catch
(
FatalBeanException
ex
)
{
return
ex
;
}
}
private
FailureAnalysis
analyzeFailure
(
Exception
failure
)
{
assertThat
(
failure
).
isNotNull
();
FailureAnalysis
analysis
=
this
.
analyzer
.
analyze
(
failure
);
if
(
analysis
!=
null
)
{
new
LoggingFailureAnalysisReporter
().
report
(
analysis
);
}
return
analysis
;
}
@ConstructorBinding
@ConfigurationProperties
(
"test"
)
static
class
ConstructorBoundProperties
{
private
final
String
name
;
ConstructorBoundProperties
(
String
name
)
{
this
.
name
=
name
;
}
String
getName
()
{
return
this
.
name
;
}
}
@Configuration
(
proxyBeanMethods
=
false
)
@Import
(
ConstructorBoundProperties
.
class
)
static
class
ShouldHaveUsedConstructorBindingPropertiesConfiguration
{
}
@ConfigurationProperties
(
"test"
)
static
class
JavaBeanBoundProperties
{
private
String
name
;
JavaBeanBoundProperties
(
String
dependency
)
{
}
String
getName
()
{
return
this
.
name
;
}
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
}
@Configuration
(
proxyBeanMethods
=
false
)
@Import
(
JavaBeanBoundProperties
.
class
)
static
class
JavaBeanBoundPropertiesConfiguration
{
}
}
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