28
28
import org .springframework .beans .factory .support .BeanDefinitionBuilder ;
29
29
import org .springframework .beans .factory .support .DefaultBeanNameGenerator ;
30
30
import org .springframework .beans .factory .support .DefaultListableBeanFactory ;
31
+ import org .springframework .context .support .AbstractApplicationContext ;
31
32
import org .springframework .context .support .AbstractRefreshableApplicationContext ;
32
33
import org .springframework .core .annotation .AnnotationUtils ;
33
34
import org .springframework .util .Assert ;
34
35
import org .springframework .util .StringUtils ;
35
36
36
37
37
38
/**
38
- * Standalone application context, accepting {@link Configuration}-annotated
39
- * class literals as input. Useful for test harnesses or any other scenario
39
+ * Standalone application context, accepting {@link Configuration @Configuration}
40
+ * -annotated class literals as input. Useful for test harnesses or any other scenario
40
41
* where XML-based configuration is unnecessary or undesired.
41
42
*
42
43
* <p>In case of multiple Configuration classes, {@link Bean}
50
51
*/
51
52
public class ConfigurationClassApplicationContext extends AbstractRefreshableApplicationContext {
52
53
53
- private final Set <Class <?>> configClasses = new LinkedHashSet <Class <?>>();
54
+ private final ConfigurationClassApplicationContext .Delegate delegate =
55
+ new ConfigurationClassApplicationContext .Delegate ();
54
56
55
57
/**
56
58
* Create a new {@link ConfigurationClassApplicationContext}, loading bean
@@ -70,7 +72,7 @@ public ConfigurationClassApplicationContext(Class<?>... configClasses) {
70
72
}
71
73
72
74
for (Class <?> configClass : configClasses ) {
73
- addConfigurationClass (configClass );
75
+ this . addConfigurationClass (configClass );
74
76
}
75
77
76
78
this .refresh ();
@@ -88,10 +90,7 @@ public ConfigurationClassApplicationContext(Class<?>... configClasses) {
88
90
* @see #refresh()
89
91
*/
90
92
public void addConfigurationClass (Class <?> configClass ) {
91
- Assert .notNull (
92
- AnnotationUtils .findAnnotation (configClass , Configuration .class ),
93
- "Class [" + configClass .getName () + "] is not annotated with @Configuration" );
94
- this .configClasses .add (configClass );
93
+ this .delegate .addConfigurationClass (configClass );
95
94
}
96
95
97
96
/**
@@ -100,30 +99,18 @@ public void addConfigurationClass(Class<?> configClass) {
100
99
* processors, such that {@literal @Autowired}, {@literal @Required}, and associated
101
100
* annotations can be used within Configuration classes.
102
101
*
103
- * <p>Configuration class bean definitions are registered with generated bean definition names.
102
+ * <p>Configuration class bean definitions are registered with generated bean definition
103
+ * names unless the {@literal value} attribute is provided to the Configuration annotation.
104
104
*
105
105
* @see AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
106
106
* @see ConfigurationClassPostProcessor
107
+ * @see DefaultBeanNameGenerator
108
+ * @see Configuration#value()
107
109
*/
108
110
@ Override
109
111
protected void loadBeanDefinitions (DefaultListableBeanFactory beanFactory )
110
112
throws IOException , BeansException {
111
-
112
- // @Autowired and friends must be enabled by default when processing @Configuration classes
113
- AnnotationConfigUtils .registerAnnotationConfigProcessors (beanFactory );
114
-
115
- for (Class <?> configClass : configClasses ) {
116
- AbstractBeanDefinition def = BeanDefinitionBuilder .rootBeanDefinition (configClass ).getBeanDefinition ();
117
-
118
- String name = AnnotationUtils .findAnnotation (configClass , Configuration .class ).value ();
119
- if (!StringUtils .hasLength (name )) {
120
- name = new DefaultBeanNameGenerator ().generateBeanName (def , beanFactory );
121
- }
122
-
123
- beanFactory .registerBeanDefinition (name , def );
124
- }
125
-
126
- new ConfigurationClassPostProcessor ().postProcessBeanFactory (beanFactory );
113
+ this .delegate .loadBeanDefinitions (beanFactory );
127
114
}
128
115
129
116
/**
@@ -138,24 +125,78 @@ protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
138
125
* @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(Class)
139
126
* @see org.springframework.beans.factory.BeanFactory#getBean(String, Class)
140
127
*/
141
- @ SuppressWarnings ("unchecked" )
142
128
public <T > T getBean (Class <T > requiredType ) {
143
- Assert .notNull (requiredType , "requiredType may not be null" );
144
-
145
- Map <String , ?> beansOfType = this .getBeansOfType (requiredType );
146
-
147
- switch (beansOfType .size ()) {
148
- case 0 :
149
- throw new NoSuchBeanDefinitionException (requiredType );
150
- case 1 :
151
- return (T ) beansOfType .values ().iterator ().next ();
152
- default :
153
- throw new NoSuchBeanDefinitionException (requiredType ,
154
- beansOfType .size () + " matching bean definitions found " +
155
- "(" + StringUtils .collectionToCommaDelimitedString (beansOfType .keySet ()) + "). " +
156
- "Consider qualifying with getBean(Class<T> beanType, String beanName) or " +
157
- "declaring one bean definition as @Primary" );
158
- }
129
+ return this .delegate .getBean (requiredType , this );
159
130
}
160
131
132
+
133
+ /**
134
+ * Encapsulates behavior common to {@link ConfigurationClassApplicationContext}
135
+ * and its {@link org.springframework.web.context.support.ConfigurationClassWebApplicationContext}
136
+ * variant. Both classes already participate in mutually exclusive superclass
137
+ * hierarchies, and this class allows for avoiding what would otherwise be a multiple
138
+ * inheritance problem through composition.
139
+ *
140
+ * <p><strong>This class is public by necessity but should be considered private and
141
+ * subject to change without notice.</strong>
142
+ */
143
+ public static class Delegate {
144
+
145
+ private final Set <Class <?>> configClasses = new LinkedHashSet <Class <?>>();
146
+
147
+ /**
148
+ * @see ConfigurationClassApplicationContext#addConfigurationClass(Class)
149
+ */
150
+ public void addConfigurationClass (Class <?> configClass ) {
151
+ Assert .notNull (
152
+ AnnotationUtils .findAnnotation (configClass , Configuration .class ),
153
+ "Class [" + configClass .getName () + "] is not annotated with @Configuration" );
154
+ this .configClasses .add (configClass );
155
+ }
156
+
157
+ /**
158
+ * @see ConfigurationClassApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)
159
+ */
160
+ public void loadBeanDefinitions (DefaultListableBeanFactory beanFactory ) {
161
+ // @Autowired and friends must be enabled by default when processing @Configuration classes
162
+ AnnotationConfigUtils .registerAnnotationConfigProcessors (beanFactory );
163
+
164
+ for (Class <?> configClass : this .configClasses ) {
165
+ AbstractBeanDefinition def = BeanDefinitionBuilder .rootBeanDefinition (configClass ).getBeanDefinition ();
166
+
167
+ String name = AnnotationUtils .findAnnotation (configClass , Configuration .class ).value ();
168
+ if (!StringUtils .hasLength (name )) {
169
+ name = new DefaultBeanNameGenerator ().generateBeanName (def , beanFactory );
170
+ }
171
+
172
+ beanFactory .registerBeanDefinition (name , def );
173
+ }
174
+
175
+ new ConfigurationClassPostProcessor ().postProcessBeanFactory (beanFactory );
176
+ }
177
+
178
+ /**
179
+ * @see ConfigurationClassApplicationContext#getBean(Class)
180
+ */
181
+ @ SuppressWarnings ("unchecked" )
182
+ public <T > T getBean (Class <T > requiredType , AbstractApplicationContext context ) {
183
+ Assert .notNull (requiredType , "requiredType may not be null" );
184
+ Assert .notNull (context , "context may not be null" );
185
+
186
+ Map <String , ?> beansOfType = context .getBeansOfType (requiredType );
187
+
188
+ switch (beansOfType .size ()) {
189
+ case 0 :
190
+ throw new NoSuchBeanDefinitionException (requiredType );
191
+ case 1 :
192
+ return (T ) beansOfType .values ().iterator ().next ();
193
+ default :
194
+ throw new NoSuchBeanDefinitionException (requiredType ,
195
+ beansOfType .size () + " matching bean definitions found " +
196
+ "(" + StringUtils .collectionToCommaDelimitedString (beansOfType .keySet ()) + "). " +
197
+ "Consider qualifying with getBean(Class<T> beanType, String beanName) or " +
198
+ "declaring one bean definition as @Primary" );
199
+ }
200
+ }
201
+ }
161
202
}
0 commit comments