18
18
19
19
import java .io .IOException ;
20
20
import java .util .ArrayList ;
21
- import java .util .Collections ;
22
21
import java .util .List ;
23
22
import java .util .Map ;
24
23
import java .util .Properties ;
78
77
*
79
78
* <p>As of Spring 3.1, {@code ContextLoader} supports injecting the root web
80
79
* application context via the {@link #ContextLoader(WebApplicationContext)}
81
- * constructor, allowing for programmatic configuration in Servlet 3.0+ environments. See
82
- * {@link org.springframework.web.WebApplicationInitializer} for usage examples.
80
+ * constructor, allowing for programmatic configuration in Servlet 3.0+ environments.
81
+ * See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
83
82
*
84
83
* @author Juergen Hoeller
85
84
* @author Colin Sampaleanu
91
90
*/
92
91
public class ContextLoader {
93
92
93
+ /**
94
+ * Config param for the root WebApplicationContext id,
95
+ * to be used as serialization id for the underlying BeanFactory: {@value}
96
+ */
97
+ public static final String CONTEXT_ID_PARAM = "contextId" ;
98
+
99
+ /**
100
+ * Name of servlet context parameter (i.e., {@value}) that can specify the
101
+ * config location for the root context, falling back to the implementation's
102
+ * default otherwise.
103
+ * @see org.springframework.web.context.support.XmlWebApplicationContext#DEFAULT_CONFIG_LOCATION
104
+ */
105
+ public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation" ;
106
+
94
107
/**
95
108
* Config param for the root WebApplicationContext implementation class to use: {@value}
96
109
* @see #determineContextClass(ServletContext)
@@ -99,25 +112,18 @@ public class ContextLoader {
99
112
public static final String CONTEXT_CLASS_PARAM = "contextClass" ;
100
113
101
114
/**
102
- * Config param for the root WebApplicationContext id,
103
- * to be used as serialization id for the underlying BeanFactory: {@value}
104
- */
105
- public static final String CONTEXT_ID_PARAM = "contextId" ;
106
-
107
- /**
108
- * Config param for which {@link ApplicationContextInitializer} classes to use
109
- * for initializing the web application context: {@value}
115
+ * Config param for {@link ApplicationContextInitializer} classes to use
116
+ * for initializing the root web application context: {@value}
110
117
* @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
111
118
*/
112
119
public static final String CONTEXT_INITIALIZER_CLASSES_PARAM = "contextInitializerClasses" ;
113
120
114
121
/**
115
- * Name of servlet context parameter (i.e., {@value}) that can specify the
116
- * config location for the root context, falling back to the implementation's
117
- * default otherwise.
118
- * @see org.springframework.web.context.support.XmlWebApplicationContext#DEFAULT_CONFIG_LOCATION
122
+ * Config param for global {@link ApplicationContextInitializer} classes to use
123
+ * for initializing all web application contexts in the current application: {@value}
124
+ * @see #customizeContext(ServletContext, ConfigurableWebApplicationContext)
119
125
*/
120
- public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation " ;
126
+ public static final String GLOBAL_INITIALIZER_CLASSES_PARAM = "globalInitializerClasses " ;
121
127
122
128
/**
123
129
* Optional servlet context parameter (i.e., "{@code locatorFactorySelector}")
@@ -147,6 +153,12 @@ public class ContextLoader {
147
153
*/
148
154
public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey" ;
149
155
156
+ /**
157
+ * Any number of these characters are considered delimiters between
158
+ * multiple values in a single init-param String value.
159
+ */
160
+ private static final String INIT_PARAM_DELIMITERS = ",; \t \n " ;
161
+
150
162
/**
151
163
* Name of the class path resource (relative to the ContextLoader class)
152
164
* that defines ContextLoader's default strategy names.
@@ -381,14 +393,71 @@ protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicati
381
393
}
382
394
383
395
wac .setServletContext (sc );
384
- String initParameter = sc .getInitParameter (CONFIG_LOCATION_PARAM );
385
- if (initParameter != null ) {
386
- wac .setConfigLocation (initParameter );
396
+ String configLocationParam = sc .getInitParameter (CONFIG_LOCATION_PARAM );
397
+ if (configLocationParam != null ) {
398
+ wac .setConfigLocation (configLocationParam );
387
399
}
400
+
401
+ // The wac environment's #initPropertySources will be called in any case when the context
402
+ // is refreshed; do it eagerly here to ensure servlet property sources are in place for
403
+ // use in any post-processing or initialization that occurs below prior to #refresh
404
+ ConfigurableEnvironment env = wac .getEnvironment ();
405
+ if (env instanceof ConfigurableWebEnvironment ) {
406
+ ((ConfigurableWebEnvironment ) env ).initPropertySources (sc , null );
407
+ }
408
+
388
409
customizeContext (sc , wac );
389
410
wac .refresh ();
390
411
}
391
412
413
+ /**
414
+ * Customize the {@link ConfigurableWebApplicationContext} created by this
415
+ * ContextLoader after config locations have been supplied to the context
416
+ * but before the context is <em>refreshed</em>.
417
+ * <p>The default implementation {@linkplain #determineContextInitializerClasses(ServletContext)
418
+ * determines} what (if any) context initializer classes have been specified through
419
+ * {@linkplain #CONTEXT_INITIALIZER_CLASSES_PARAM context init parameters} and
420
+ * {@linkplain ApplicationContextInitializer#initialize invokes each} with the
421
+ * given web application context.
422
+ * <p>Any {@code ApplicationContextInitializers} implementing
423
+ * {@link org.springframework.core.Ordered Ordered} or marked with @{@link
424
+ * org.springframework.core.annotation.Order Order} will be sorted appropriately.
425
+ * @param sc the current servlet context
426
+ * @param wac the newly created application context
427
+ * @see #createWebApplicationContext(ServletContext, ApplicationContext)
428
+ * @see #CONTEXT_INITIALIZER_CLASSES_PARAM
429
+ * @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
430
+ */
431
+ protected void customizeContext (ServletContext sc , ConfigurableWebApplicationContext wac ) {
432
+ List <Class <ApplicationContextInitializer <ConfigurableApplicationContext >>> initializerClasses =
433
+ determineContextInitializerClasses (sc );
434
+ if (initializerClasses .isEmpty ()) {
435
+ // no ApplicationContextInitializers have been declared -> nothing to do
436
+ return ;
437
+ }
438
+
439
+ ArrayList <ApplicationContextInitializer <ConfigurableApplicationContext >> initializerInstances =
440
+ new ArrayList <ApplicationContextInitializer <ConfigurableApplicationContext >>();
441
+
442
+ for (Class <ApplicationContextInitializer <ConfigurableApplicationContext >> initializerClass : initializerClasses ) {
443
+ Class <?> initializerContextClass =
444
+ GenericTypeResolver .resolveTypeArgument (initializerClass , ApplicationContextInitializer .class );
445
+ if (initializerContextClass != null ) {
446
+ Assert .isAssignable (initializerContextClass , wac .getClass (), String .format (
447
+ "Could not add context initializer [%s] since its generic parameter [%s] " +
448
+ "is not assignable from the type of application context used by this " +
449
+ "context loader [%s]: " , initializerClass .getName (), initializerContextClass .getName (),
450
+ wac .getClass ().getName ()));
451
+ }
452
+ initializerInstances .add (BeanUtils .instantiateClass (initializerClass ));
453
+ }
454
+
455
+ AnnotationAwareOrderComparator .sort (initializerInstances );
456
+ for (ApplicationContextInitializer <ConfigurableApplicationContext > initializer : initializerInstances ) {
457
+ initializer .initialize (wac );
458
+ }
459
+ }
460
+
392
461
/**
393
462
* Return the WebApplicationContext implementation class to use, either the
394
463
* default XmlWebApplicationContext or a custom context class if specified.
@@ -426,80 +495,38 @@ protected Class<?> determineContextClass(ServletContext servletContext) {
426
495
* @param servletContext current servlet context
427
496
* @see #CONTEXT_INITIALIZER_CLASSES_PARAM
428
497
*/
429
- @ SuppressWarnings ("unchecked" )
430
498
protected List <Class <ApplicationContextInitializer <ConfigurableApplicationContext >>>
431
499
determineContextInitializerClasses (ServletContext servletContext ) {
432
- String classNames = servletContext . getInitParameter ( CONTEXT_INITIALIZER_CLASSES_PARAM );
500
+
433
501
List <Class <ApplicationContextInitializer <ConfigurableApplicationContext >>> classes =
434
- new ArrayList <Class <ApplicationContextInitializer <ConfigurableApplicationContext >>>();
435
- if (classNames != null ) {
436
- for (String className : StringUtils .tokenizeToStringArray (classNames , "," )) {
437
- try {
438
- Class <?> clazz = ClassUtils .forName (className , ClassUtils .getDefaultClassLoader ());
439
- Assert .isAssignable (ApplicationContextInitializer .class , clazz ,
440
- "class [" + className + "] must implement ApplicationContextInitializer" );
441
- classes .add ((Class <ApplicationContextInitializer <ConfigurableApplicationContext >>)clazz );
442
- }
443
- catch (ClassNotFoundException ex ) {
444
- throw new ApplicationContextException (
445
- "Failed to load context initializer class [" + className + "]" , ex );
446
- }
447
- }
448
- }
449
- return classes ;
450
- }
502
+ new ArrayList <Class <ApplicationContextInitializer <ConfigurableApplicationContext >>>();
451
503
452
- /**
453
- * Customize the {@link ConfigurableWebApplicationContext} created by this
454
- * ContextLoader after config locations have been supplied to the context
455
- * but before the context is <em>refreshed</em>.
456
- * <p>The default implementation {@linkplain #determineContextInitializerClasses(ServletContext)
457
- * determines} what (if any) context initializer classes have been specified through
458
- * {@linkplain #CONTEXT_INITIALIZER_CLASSES_PARAM context init parameters} and
459
- * {@linkplain ApplicationContextInitializer#initialize invokes each} with the
460
- * given web application context.
461
- * <p>Any {@code ApplicationContextInitializers} implementing
462
- * {@link org.springframework.core.Ordered Ordered} or marked with @{@link
463
- * org.springframework.core.annotation.Order Order} will be sorted appropriately.
464
- * @param servletContext the current servlet context
465
- * @param applicationContext the newly created application context
466
- * @see #createWebApplicationContext(ServletContext, ApplicationContext)
467
- * @see #CONTEXT_INITIALIZER_CLASSES_PARAM
468
- * @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
469
- */
470
- protected void customizeContext (ServletContext servletContext , ConfigurableWebApplicationContext applicationContext ) {
471
- List <Class <ApplicationContextInitializer <ConfigurableApplicationContext >>> initializerClasses =
472
- determineContextInitializerClasses (servletContext );
473
- if (initializerClasses .size () == 0 ) {
474
- // no ApplicationContextInitializers have been declared -> nothing to do
475
- return ;
504
+ String globalClassNames = servletContext .getInitParameter (GLOBAL_INITIALIZER_CLASSES_PARAM );
505
+ if (globalClassNames != null ) {
506
+ for (String className : StringUtils .tokenizeToStringArray (globalClassNames , INIT_PARAM_DELIMITERS )) {
507
+ classes .add (loadInitializerClass (className ));
508
+ }
476
509
}
477
510
478
- Class <?> contextClass = applicationContext .getClass ();
479
- ArrayList <ApplicationContextInitializer <ConfigurableApplicationContext >> initializerInstances =
480
- new ArrayList <ApplicationContextInitializer <ConfigurableApplicationContext >>();
481
-
482
- for (Class <ApplicationContextInitializer <ConfigurableApplicationContext >> initializerClass : initializerClasses ) {
483
- Class <?> initializerContextClass =
484
- GenericTypeResolver .resolveTypeArgument (initializerClass , ApplicationContextInitializer .class );
485
- if (initializerContextClass != null ) {
486
- Assert .isAssignable (initializerContextClass , contextClass , String .format (
487
- "Could not add context initializer [%s] as its generic parameter [%s] " +
488
- "is not assignable from the type of application context used by this " +
489
- "context loader [%s]: " , initializerClass .getName (), initializerContextClass .getName (),
490
- contextClass .getName ()));
511
+ String localClassNames = servletContext .getInitParameter (CONTEXT_INITIALIZER_CLASSES_PARAM );
512
+ if (localClassNames != null ) {
513
+ for (String className : StringUtils .tokenizeToStringArray (localClassNames , INIT_PARAM_DELIMITERS )) {
514
+ classes .add (loadInitializerClass (className ));
491
515
}
492
- initializerInstances .add (BeanUtils .instantiateClass (initializerClass ));
493
516
}
494
517
495
- ConfigurableEnvironment env = applicationContext .getEnvironment ();
496
- if (env instanceof ConfigurableWebEnvironment ) {
497
- ((ConfigurableWebEnvironment )env ).initPropertySources (servletContext , null );
498
- }
518
+ return classes ;
519
+ }
499
520
500
- Collections .sort (initializerInstances , new AnnotationAwareOrderComparator ());
501
- for (ApplicationContextInitializer <ConfigurableApplicationContext > initializer : initializerInstances ) {
502
- initializer .initialize (applicationContext );
521
+ @ SuppressWarnings ("unchecked" )
522
+ private Class <ApplicationContextInitializer <ConfigurableApplicationContext >> loadInitializerClass (String className ) {
523
+ try {
524
+ Class <?> clazz = ClassUtils .forName (className , ClassUtils .getDefaultClassLoader ());
525
+ Assert .isAssignable (ApplicationContextInitializer .class , clazz );
526
+ return (Class <ApplicationContextInitializer <ConfigurableApplicationContext >>) clazz ;
527
+ }
528
+ catch (ClassNotFoundException ex ) {
529
+ throw new ApplicationContextException ("Failed to load context initializer class [" + className + "]" , ex );
503
530
}
504
531
}
505
532
0 commit comments