16
16
17
17
package org .springframework .boot .orm .jpa ;
18
18
19
- import java .util .ArrayList ;
20
19
import java .util .Arrays ;
20
+ import java .util .Collections ;
21
21
import java .util .LinkedHashSet ;
22
22
import java .util .Set ;
23
23
24
24
import org .springframework .beans .BeansException ;
25
25
import org .springframework .beans .factory .SmartInitializingSingleton ;
26
26
import org .springframework .beans .factory .config .BeanDefinition ;
27
27
import org .springframework .beans .factory .config .BeanPostProcessor ;
28
+ import org .springframework .beans .factory .config .ConstructorArgumentValues .ValueHolder ;
28
29
import org .springframework .beans .factory .support .BeanDefinitionRegistry ;
29
30
import org .springframework .beans .factory .support .GenericBeanDefinition ;
30
31
import org .springframework .context .annotation .ImportBeanDefinitionRegistrar ;
40
41
* {@link ImportBeanDefinitionRegistrar} used by {@link EntityScan}.
41
42
*
42
43
* @author Phillip Webb
44
+ * @author Oliver Gierke
43
45
*/
44
46
class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
45
47
@@ -48,42 +50,64 @@ class EntityScanRegistrar implements ImportBeanDefinitionRegistrar {
48
50
@ Override
49
51
public void registerBeanDefinitions (AnnotationMetadata importingClassMetadata ,
50
52
BeanDefinitionRegistry registry ) {
53
+ Set <String > packagesToScan = getPackagesToScan (importingClassMetadata );
51
54
if (!registry .containsBeanDefinition (BEAN_NAME )) {
52
- GenericBeanDefinition beanDefinition = new GenericBeanDefinition ();
53
- beanDefinition .setBeanClass (EntityScanBeanPostProcessor .class );
54
- beanDefinition .getConstructorArgumentValues ().addGenericArgumentValue (
55
- getPackagesToScan (importingClassMetadata ));
56
- beanDefinition .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
57
- // We don't need this one to be post processed otherwise it can cause a
58
- // cascade of bean instantiation that we would rather avoid.
59
- beanDefinition .setSynthetic (true );
60
- registry .registerBeanDefinition (BEAN_NAME , beanDefinition );
55
+ addEntityScanBeanPostProcessor (registry , packagesToScan );
56
+ }
57
+ else {
58
+ updateEntityScanBeanPostProcessor (registry , packagesToScan );
61
59
}
62
60
}
63
61
64
- private String [] getPackagesToScan (AnnotationMetadata metadata ) {
62
+ private Set < String > getPackagesToScan (AnnotationMetadata metadata ) {
65
63
AnnotationAttributes attributes = AnnotationAttributes .fromMap (metadata
66
64
.getAnnotationAttributes (EntityScan .class .getName ()));
67
65
String [] value = attributes .getStringArray ("value" );
68
66
String [] basePackages = attributes .getStringArray ("basePackages" );
69
67
Class <?>[] basePackageClasses = attributes .getClassArray ("basePackageClasses" );
70
-
71
68
if (!ObjectUtils .isEmpty (value )) {
72
69
Assert .state (ObjectUtils .isEmpty (basePackages ),
73
70
"@EntityScan basePackages and value attributes are mutually exclusive" );
74
71
}
75
-
76
72
Set <String > packagesToScan = new LinkedHashSet <String >();
77
73
packagesToScan .addAll (Arrays .asList (value ));
78
74
packagesToScan .addAll (Arrays .asList (basePackages ));
79
75
for (Class <?> basePackageClass : basePackageClasses ) {
80
76
packagesToScan .add (ClassUtils .getPackageName (basePackageClass ));
81
77
}
82
78
if (packagesToScan .isEmpty ()) {
83
- return new String [] { ClassUtils .getPackageName (metadata .getClassName ()) };
79
+ return Collections .singleton (ClassUtils .getPackageName (metadata
80
+ .getClassName ()));
84
81
}
85
- return new ArrayList <String >(packagesToScan ).toArray (new String [packagesToScan
86
- .size ()]);
82
+ return packagesToScan ;
83
+ }
84
+
85
+ private void addEntityScanBeanPostProcessor (BeanDefinitionRegistry registry ,
86
+ Set <String > packagesToScan ) {
87
+ GenericBeanDefinition beanDefinition = new GenericBeanDefinition ();
88
+ beanDefinition .setBeanClass (EntityScanBeanPostProcessor .class );
89
+ beanDefinition .getConstructorArgumentValues ().addGenericArgumentValue (
90
+ toArray (packagesToScan ));
91
+ beanDefinition .setRole (BeanDefinition .ROLE_INFRASTRUCTURE );
92
+ // We don't need this one to be post processed otherwise it can cause a
93
+ // cascade of bean instantiation that we would rather avoid.
94
+ beanDefinition .setSynthetic (true );
95
+ registry .registerBeanDefinition (BEAN_NAME , beanDefinition );
96
+ }
97
+
98
+ private void updateEntityScanBeanPostProcessor (BeanDefinitionRegistry registry ,
99
+ Set <String > packagesToScan ) {
100
+ BeanDefinition definition = registry .getBeanDefinition (BEAN_NAME );
101
+ ValueHolder constructorArguments = definition .getConstructorArgumentValues ()
102
+ .getGenericArgumentValue (String [].class );
103
+ Set <String > mergedPackages = new LinkedHashSet <String >();
104
+ mergedPackages .addAll (Arrays .asList ((String []) constructorArguments .getValue ()));
105
+ mergedPackages .addAll (packagesToScan );
106
+ constructorArguments .setValue (toArray (mergedPackages ));
107
+ }
108
+
109
+ private String [] toArray (Set <String > set ) {
110
+ return set .toArray (new String [set .size ()]);
87
111
}
88
112
89
113
/**
0 commit comments