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
70472b36
Commit
70472b36
authored
Mar 01, 2017
by
Andy Wilkinson
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch '1.4.x' into 1.5.x
parents
4390c811
59d3a79c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
175 additions
and
39 deletions
+175
-39
BeanTypeRegistry.java
...mework/boot/autoconfigure/condition/BeanTypeRegistry.java
+40
-12
OnBeanCondition.java
...amework/boot/autoconfigure/condition/OnBeanCondition.java
+24
-27
ConditionalOnBeanTests.java
.../boot/autoconfigure/condition/ConditionalOnBeanTests.java
+78
-0
ConditionalOnMissingBeanTests.java
...utoconfigure/condition/ConditionalOnMissingBeanTests.java
+33
-0
No files found.
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/BeanTypeRegistry.java
View file @
70472b36
...
@@ -16,6 +16,7 @@
...
@@ -16,6 +16,7 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.HashMap
;
...
@@ -40,6 +41,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
...
@@ -40,6 +41,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
import
org.springframework.beans.factory.support.DefaultListableBeanFactory
;
import
org.springframework.beans.factory.support.DefaultListableBeanFactory
;
import
org.springframework.beans.factory.support.RootBeanDefinition
;
import
org.springframework.beans.factory.support.RootBeanDefinition
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.ResolvableType
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.core.type.MethodMetadata
;
import
org.springframework.core.type.MethodMetadata
;
import
org.springframework.core.type.StandardMethodMetadata
;
import
org.springframework.core.type.StandardMethodMetadata
;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
...
@@ -85,7 +87,7 @@ final class BeanTypeRegistry implements SmartInitializingSingleton {
...
@@ -85,7 +87,7 @@ final class BeanTypeRegistry implements SmartInitializingSingleton {
* @param beanFactory the source bean factory
* @param beanFactory the source bean factory
* @return the {@link BeanTypeRegistry} for the given bean factory
* @return the {@link BeanTypeRegistry} for the given bean factory
*/
*/
public
static
BeanTypeRegistry
create
(
ListableBeanFactory
beanFactory
)
{
static
BeanTypeRegistry
get
(
ListableBeanFactory
beanFactory
)
{
Assert
.
isInstanceOf
(
DefaultListableBeanFactory
.
class
,
beanFactory
);
Assert
.
isInstanceOf
(
DefaultListableBeanFactory
.
class
,
beanFactory
);
DefaultListableBeanFactory
listableBeanFactory
=
(
DefaultListableBeanFactory
)
beanFactory
;
DefaultListableBeanFactory
listableBeanFactory
=
(
DefaultListableBeanFactory
)
beanFactory
;
Assert
.
isTrue
(
listableBeanFactory
.
isAllowEagerClassLoading
(),
Assert
.
isTrue
(
listableBeanFactory
.
isAllowEagerClassLoading
(),
...
@@ -101,26 +103,39 @@ final class BeanTypeRegistry implements SmartInitializingSingleton {
...
@@ -101,26 +103,39 @@ final class BeanTypeRegistry implements SmartInitializingSingleton {
/**
/**
* Return the names of beans matching the given type (including subclasses), judging
* Return the names of beans matching the given type (including subclasses), judging
* from either bean definitions or the value of {@code getObjectType} in the case of
* from either bean definitions or the value of {@link FactoryBean#getObjectType()} in
* FactoryBeans. Will include singletons but not cause early bean initialization.
* the case of {@link FactoryBean FactoryBeans}. Will include singletons but will not
* cause early bean initialization.
* @param type the class or interface to match (must not be {@code null})
* @param type the class or interface to match (must not be {@code null})
* @return the names of beans (or objects created by FactoryBeans) matching the given
* @return the names of beans (or objects created by FactoryBeans) matching the given
* object type (including subclasses), or an empty set if none
* object type (including subclasses), or an empty set if none
*/
*/
Set
<
String
>
getNamesForType
(
Class
<?>
type
)
{
Set
<
String
>
getNamesForType
(
Class
<?>
type
)
{
if
(
this
.
lastBeanDefinitionCount
!=
this
.
beanFactory
.
getBeanDefinitionCount
())
{
updateTypesIfNecessary
();
Iterator
<
String
>
names
=
this
.
beanFactory
.
getBeanNamesIterator
();
Set
<
String
>
matches
=
new
LinkedHashSet
<
String
>();
while
(
names
.
hasNext
())
{
for
(
Map
.
Entry
<
String
,
Class
<?>>
entry
:
this
.
beanTypes
.
entrySet
())
{
String
name
=
names
.
next
();
if
(
entry
.
getValue
()
!=
null
&&
type
.
isAssignableFrom
(
entry
.
getValue
()))
{
if
(!
this
.
beanTypes
.
containsKey
(
name
))
{
matches
.
add
(
entry
.
getKey
());
addBeanType
(
name
);
}
}
}
this
.
lastBeanDefinitionCount
=
this
.
beanFactory
.
getBeanDefinitionCount
();
}
}
return
matches
;
}
/**
* Returns the names of beans annotated with the given {@code annotation}, judging
* from either bean definitions or the value of {@link FactoryBean#getObjectType()} in
* the case of {@link FactoryBean FactoryBeans}. Will include singletons but will not
* cause early bean initialization.
* @param annotation the annotation to match (must not be {@code null})
* @return the names of beans (or objects created by FactoryBeans) annoated with the
* given annotation, or an empty set if none
*/
Set
<
String
>
getNamesForAnnotation
(
Class
<?
extends
Annotation
>
annotation
)
{
updateTypesIfNecessary
();
Set
<
String
>
matches
=
new
LinkedHashSet
<
String
>();
Set
<
String
>
matches
=
new
LinkedHashSet
<
String
>();
for
(
Map
.
Entry
<
String
,
Class
<?>>
entry
:
this
.
beanTypes
.
entrySet
())
{
for
(
Map
.
Entry
<
String
,
Class
<?>>
entry
:
this
.
beanTypes
.
entrySet
())
{
if
(
entry
.
getValue
()
!=
null
&&
type
.
isAssignableFrom
(
entry
.
getValue
()))
{
if
(
entry
.
getValue
()
!=
null
&&
AnnotationUtils
.
findAnnotation
(
entry
.
getValue
(),
annotation
)
!=
null
)
{
matches
.
add
(
entry
.
getKey
());
matches
.
add
(
entry
.
getKey
());
}
}
}
}
...
@@ -183,6 +198,19 @@ final class BeanTypeRegistry implements SmartInitializingSingleton {
...
@@ -183,6 +198,19 @@ final class BeanTypeRegistry implements SmartInitializingSingleton {
&&
!
this
.
beanFactory
.
containsSingleton
(
factoryBeanName
));
&&
!
this
.
beanFactory
.
containsSingleton
(
factoryBeanName
));
}
}
private
void
updateTypesIfNecessary
()
{
if
(
this
.
lastBeanDefinitionCount
!=
this
.
beanFactory
.
getBeanDefinitionCount
())
{
Iterator
<
String
>
names
=
this
.
beanFactory
.
getBeanNamesIterator
();
while
(
names
.
hasNext
())
{
String
name
=
names
.
next
();
if
(!
this
.
beanTypes
.
containsKey
(
name
))
{
addBeanType
(
name
);
}
}
this
.
lastBeanDefinitionCount
=
this
.
beanFactory
.
getBeanDefinitionCount
();
}
}
/**
/**
* Attempt to guess the type that a {@link FactoryBean} will return based on the
* Attempt to guess the type that a {@link FactoryBean} will return based on the
* generics in its method signature.
* generics in its method signature.
...
...
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java
View file @
70472b36
...
@@ -21,6 +21,7 @@ import java.util.ArrayList;
...
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashSet
;
import
java.util.LinkedHashSet
;
import
java.util.LinkedHashSet
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.Set
;
...
@@ -56,8 +57,6 @@ import org.springframework.util.StringUtils;
...
@@ -56,8 +57,6 @@ import org.springframework.util.StringUtils;
@Order
(
Ordered
.
LOWEST_PRECEDENCE
)
@Order
(
Ordered
.
LOWEST_PRECEDENCE
)
class
OnBeanCondition
extends
SpringBootCondition
implements
ConfigurationCondition
{
class
OnBeanCondition
extends
SpringBootCondition
implements
ConfigurationCondition
{
private
static
final
String
[]
NO_BEANS
=
{};
/**
/**
* Bean definition attribute name for factory beans to signal their product type (if
* Bean definition attribute name for factory beans to signal their product type (if
* known and it can't be deduced from the factory bean class).
* known and it can't be deduced from the factory bean class).
...
@@ -183,7 +182,7 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
...
@@ -183,7 +182,7 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
private
void
collectBeanNamesForType
(
Set
<
String
>
result
,
private
void
collectBeanNamesForType
(
Set
<
String
>
result
,
ListableBeanFactory
beanFactory
,
Class
<?>
type
,
boolean
considerHierarchy
)
{
ListableBeanFactory
beanFactory
,
Class
<?>
type
,
boolean
considerHierarchy
)
{
result
.
addAll
(
BeanTypeRegistry
.
create
(
beanFactory
).
getNamesForType
(
type
));
result
.
addAll
(
BeanTypeRegistry
.
get
(
beanFactory
).
getNamesForType
(
type
));
if
(
considerHierarchy
&&
beanFactory
instanceof
HierarchicalBeanFactory
)
{
if
(
considerHierarchy
&&
beanFactory
instanceof
HierarchicalBeanFactory
)
{
BeanFactory
parent
=
((
HierarchicalBeanFactory
)
beanFactory
)
BeanFactory
parent
=
((
HierarchicalBeanFactory
)
beanFactory
)
.
getParentBeanFactory
();
.
getParentBeanFactory
();
...
@@ -197,34 +196,32 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
...
@@ -197,34 +196,32 @@ class OnBeanCondition extends SpringBootCondition implements ConfigurationCondit
private
String
[]
getBeanNamesForAnnotation
(
private
String
[]
getBeanNamesForAnnotation
(
ConfigurableListableBeanFactory
beanFactory
,
String
type
,
ConfigurableListableBeanFactory
beanFactory
,
String
type
,
ClassLoader
classLoader
,
boolean
considerHierarchy
)
throws
LinkageError
{
ClassLoader
classLoader
,
boolean
considerHierarchy
)
throws
LinkageError
{
S
tring
[]
result
=
NO_BEANS
;
S
et
<
String
>
names
=
new
HashSet
<
String
>()
;
try
{
try
{
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
Class
<?
extends
Annotation
>
typeClass
=
(
Class
<?
extends
Annotation
>)
ClassUtils
Class
<?
extends
Annotation
>
annotationType
=
(
Class
<?
extends
Annotation
>)
ClassUtils
.
forName
(
type
,
classLoader
);
.
forName
(
type
,
classLoader
);
result
=
beanFactory
.
getBeanNamesForAnnotation
(
typeClass
);
collectBeanNamesForAnnotation
(
names
,
beanFactory
,
annotationType
,
if
(
considerHierarchy
)
{
considerHierarchy
);
if
(
beanFactory
.
getParentBeanFactory
()
instanceof
ConfigurableListableBeanFactory
)
{
String
[]
parentResult
=
getBeanNamesForAnnotation
(
(
ConfigurableListableBeanFactory
)
beanFactory
.
getParentBeanFactory
(),
type
,
classLoader
,
true
);
List
<
String
>
resultList
=
new
ArrayList
<
String
>();
resultList
.
addAll
(
Arrays
.
asList
(
result
));
for
(
String
beanName
:
parentResult
)
{
if
(!
resultList
.
contains
(
beanName
)
&&
!
beanFactory
.
containsLocalBean
(
beanName
))
{
resultList
.
add
(
beanName
);
}
}
result
=
StringUtils
.
toStringArray
(
resultList
);
}
}
return
result
;
}
}
catch
(
ClassNotFoundException
ex
)
{
catch
(
ClassNotFoundException
e
)
{
return
NO_BEANS
;
// Continue
}
return
StringUtils
.
toStringArray
(
names
);
}
private
void
collectBeanNamesForAnnotation
(
Set
<
String
>
names
,
ListableBeanFactory
beanFactory
,
Class
<?
extends
Annotation
>
annotationType
,
boolean
considerHierarchy
)
{
names
.
addAll
(
BeanTypeRegistry
.
get
(
beanFactory
).
getNamesForAnnotation
(
annotationType
));
if
(
considerHierarchy
)
{
BeanFactory
parent
=
((
HierarchicalBeanFactory
)
beanFactory
)
.
getParentBeanFactory
();
if
(
parent
instanceof
ListableBeanFactory
)
{
collectBeanNamesForAnnotation
(
names
,
(
ListableBeanFactory
)
parent
,
annotationType
,
considerHierarchy
);
}
}
}
}
}
...
...
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnBeanTests.java
View file @
70472b36
...
@@ -16,10 +16,16 @@
...
@@ -16,10 +16,16 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.util.Date
;
import
java.util.Date
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.springframework.beans.factory.FactoryBean
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.RootBeanDefinition
;
import
org.springframework.beans.factory.support.RootBeanDefinition
;
import
org.springframework.boot.test.util.EnvironmentTestUtils
;
import
org.springframework.boot.test.util.EnvironmentTestUtils
;
...
@@ -124,6 +130,15 @@ public class ConditionalOnBeanTests {
...
@@ -124,6 +130,15 @@ public class ConditionalOnBeanTests {
this
.
context
.
refresh
();
this
.
context
.
refresh
();
}
}
@Test
public
void
beanProducedByFactoryBeanIsConsideredWhenMatchingOnAnnotation
()
{
this
.
context
.
register
(
FactoryBeanConfiguration
.
class
,
OnAnnotationWithFactoryBeanConfiguration
.
class
);
this
.
context
.
refresh
();
assertThat
(
this
.
context
.
containsBean
(
"bar"
)).
isTrue
();
assertThat
(
this
.
context
.
getBeansOfType
(
ExampleBean
.
class
)).
hasSize
(
1
);
}
@Configuration
@Configuration
@ConditionalOnBean
(
name
=
"foo"
)
@ConditionalOnBean
(
name
=
"foo"
)
protected
static
class
OnBeanNameConfiguration
{
protected
static
class
OnBeanNameConfiguration
{
...
@@ -220,6 +235,27 @@ public class ConditionalOnBeanTests {
...
@@ -220,6 +235,27 @@ public class ConditionalOnBeanTests {
}
}
@Configuration
static
class
FactoryBeanConfiguration
{
@Bean
public
ExampleFactoryBean
exampleBeanFactoryBean
()
{
return
new
ExampleFactoryBean
();
}
}
@Configuration
@ConditionalOnBean
(
annotation
=
TestAnnotation
.
class
)
static
class
OnAnnotationWithFactoryBeanConfiguration
{
@Bean
public
String
bar
()
{
return
"bar"
;
}
}
protected
static
class
WithPropertyPlaceholderClassNameRegistrar
protected
static
class
WithPropertyPlaceholderClassNameRegistrar
implements
ImportBeanDefinitionRegistrar
{
implements
ImportBeanDefinitionRegistrar
{
...
@@ -233,4 +269,46 @@ public class ConditionalOnBeanTests {
...
@@ -233,4 +269,46 @@ public class ConditionalOnBeanTests {
}
}
public
static
class
ExampleFactoryBean
implements
FactoryBean
<
ExampleBean
>
{
@Override
public
ExampleBean
getObject
()
throws
Exception
{
return
new
ExampleBean
(
"fromFactory"
);
}
@Override
public
Class
<?>
getObjectType
()
{
return
ExampleBean
.
class
;
}
@Override
public
boolean
isSingleton
()
{
return
false
;
}
}
@TestAnnotation
public
static
class
ExampleBean
{
private
String
value
;
public
ExampleBean
(
String
value
)
{
this
.
value
=
value
;
}
@Override
public
String
toString
()
{
return
this
.
value
;
}
}
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
TestAnnotation
{
}
}
}
spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/condition/ConditionalOnMissingBeanTests.java
View file @
70472b36
...
@@ -16,6 +16,11 @@
...
@@ -16,6 +16,11 @@
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
package
org
.
springframework
.
boot
.
autoconfigure
.
condition
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.util.Date
;
import
java.util.Date
;
import
org.junit.Test
;
import
org.junit.Test
;
...
@@ -313,6 +318,15 @@ public class ConditionalOnMissingBeanTests {
...
@@ -313,6 +318,15 @@ public class ConditionalOnMissingBeanTests {
assertThat
(
child
.
getBeansOfType
(
ExampleBean
.
class
)).
hasSize
(
2
);
assertThat
(
child
.
getBeansOfType
(
ExampleBean
.
class
)).
hasSize
(
2
);
}
}
@Test
public
void
beanProducedByFactoryBeanIsConsideredWhenMatchingOnAnnotation
()
{
this
.
context
.
register
(
ConcreteFactoryBeanConfiguration
.
class
,
OnAnnotationWithFactoryBeanConfiguration
.
class
);
this
.
context
.
refresh
();
assertThat
(
this
.
context
.
containsBean
(
"bar"
)).
isFalse
();
assertThat
(
this
.
context
.
getBeansOfType
(
ExampleBean
.
class
)).
hasSize
(
1
);
}
@Configuration
@Configuration
protected
static
class
OnBeanInParentsConfiguration
{
protected
static
class
OnBeanInParentsConfiguration
{
...
@@ -540,6 +554,17 @@ public class ConditionalOnMissingBeanTests {
...
@@ -540,6 +554,17 @@ public class ConditionalOnMissingBeanTests {
}
}
@Configuration
@ConditionalOnMissingBean
(
annotation
=
TestAnnotation
.
class
)
protected
static
class
OnAnnotationWithFactoryBeanConfiguration
{
@Bean
public
String
bar
()
{
return
"bar"
;
}
}
@Configuration
@Configuration
@EnableScheduling
@EnableScheduling
protected
static
class
FooConfiguration
{
protected
static
class
FooConfiguration
{
...
@@ -594,6 +619,7 @@ public class ConditionalOnMissingBeanTests {
...
@@ -594,6 +619,7 @@ public class ConditionalOnMissingBeanTests {
}
}
@TestAnnotation
public
static
class
ExampleBean
{
public
static
class
ExampleBean
{
private
String
value
;
private
String
value
;
...
@@ -663,4 +689,11 @@ public class ConditionalOnMissingBeanTests {
...
@@ -663,4 +689,11 @@ public class ConditionalOnMissingBeanTests {
}
}
@Target
(
ElementType
.
TYPE
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Documented
public
@interface
TestAnnotation
{
}
}
}
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