diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java index 23bdf1a40aa..f293cba5995 100644 --- a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -45,7 +45,8 @@ import org.springframework.util.Assert; * @see ClassPathBeanDefinitionScanner * @see org.springframework.context.support.GenericXmlApplicationContext */ -public class AnnotationConfigApplicationContext extends GenericApplicationContext { +public class AnnotationConfigApplicationContext extends GenericApplicationContext + implements AnnotationConfigCapableApplicationContext { private final AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(this); @@ -101,8 +102,9 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex } /** - * Set the BeanNameGenerator to use for detected bean classes. - *
Default is a {@link AnnotationBeanNameGenerator}. + * {@inheritDoc} + *
Any call to this method must occur prior to calls to {@link #register(Class...)} + * and/or {@link #scan(String...)}. */ public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { this.reader.setBeanNameGenerator(beanNameGenerator); @@ -110,37 +112,20 @@ public class AnnotationConfigApplicationContext extends GenericApplicationContex } /** - * Set the ScopeMetadataResolver to use for detected bean classes. - *
The default is an {@link AnnotationScopeMetadataResolver}. + * {@inheritDoc} + *
Any call to this method must occur prior to calls to {@link #register(Class...)} + * and/or {@link #scan(String...)}. */ public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) { this.reader.setScopeMetadataResolver(scopeMetadataResolver); this.scanner.setScopeMetadataResolver(scopeMetadataResolver); } - /** - * Register an annotated class to be processed. Allows for programmatically - * building a {@link AnnotationConfigApplicationContext}. Note that - * {@link AnnotationConfigApplicationContext#refresh()} must be called in - * order for the context to fully process the new class. - *
Calls to {@link #register} are idempotent; adding the same - * annotated class more than once has no additional effect. - * @param annotatedClasses one or more annotated classes, - * e.g. {@link Configuration @Configuration} classes - * @see #refresh() - */ public void register(Class>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); this.reader.register(annotatedClasses); } - /** - * Perform a scan within the specified base packages. - * Note that {@link AnnotationConfigApplicationContext#refresh()} must be - * called in order for the context to fully process the new class. - * @param basePackages the packages to check for annotated classes - * @see #refresh() - */ public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); this.scanner.scan(basePackages); diff --git a/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigCapableApplicationContext.java b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigCapableApplicationContext.java new file mode 100644 index 00000000000..61380127898 --- /dev/null +++ b/org.springframework.context/src/main/java/org/springframework/context/annotation/AnnotationConfigCapableApplicationContext.java @@ -0,0 +1,92 @@ +/* + * Copyright 2002-2011 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 + * + * http://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.context.annotation; + +import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.ConfigurableApplicationContext; + +/** + * Extension of the {@link ConfigurableApplicationContext} interface to be implemented by + * application contexts that are capable of registering or scanning for annotated classes + * including @{@link Configuration} classes. + * + *
This subinterface is not intended for everyday use: + * {@link AnnotationConfigApplicationContext} and its web variant + * {@code AnnotationConfigWebApplicationContext} should be used directly in most cases. + * + *
The notable exception to the above is when designing + * {@link org.springframework.context.ApplicationContextInitializer + * ApplicationContextInitializer} (ACI) implementations: it may be desirable to design an + * ACI such that it may be used interchangeably against a standalone or web-capable + * "AnnotationConfig" application context. For example: + *
+ * public class MyACI
+ * implements ApplicationContextInitializer<AnnotationConfigCapableApplicationContext> {
+ * void initialize(AnnotationConfigCapableApplicationContext context) {
+ * context.register(MyConfig1.class, MyConfig2.class);
+ * context.scan("pkg1", "pkg2");
+ * // ...
+ * }
+ * }
+ *
+ * See {@link org.springframework.context.ApplicationContextInitializer
+ * ApplicationContextInitializer} Javadoc for further usage details.
+ *
+ * @author Chris Beams
+ * @since 3.1
+ * @see AnnotationConfigApplicationContext
+ * @see org.springframework.web.context.support.AnnotationConfigWebApplicationContext
+ * @see org.springframework.context.ApplicationContextInitializer
+ */
+public interface AnnotationConfigCapableApplicationContext extends ConfigurableApplicationContext {
+
+ /**
+ * Set the {@link ScopeMetadataResolver} to use for detected bean classes.
+ * The default is an {@link AnnotationScopeMetadataResolver}. + */ + void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver); + + /** + * Set the {@link BeanNameGenerator} to use for detected bean classes. + *
The default is an {@link AnnotationBeanNameGenerator}. + */ + void setBeanNameGenerator(BeanNameGenerator beanNameGenerator); + + /** + * Register one or more annotated classes to be processed. + * Note that {@link #refresh()} must be called in order for the context to fully + * process the new class. + *
Calls to {@link #register} are idempotent; adding the same + * annotated class more than once has no additional effect. + * @param annotatedClasses one or more annotated classes, + * e.g. {@link Configuration @Configuration} classes + * @see #scan(String...) + * @see #refresh() + */ + void register(Class>... annotatedClasses); + + /** + * Perform a scan within the specified base packages. + * Note that {@link #refresh()} must be called in order for the context to + * fully process the new class. + * @param basePackages the packages to check for annotated classes + * @see #register(Class...) + * @see #refresh() + */ + void scan(String... basePackages); + +} diff --git a/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java b/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java index f3c79d2ee7f..2b0a61d5150 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java +++ b/org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2011 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. @@ -19,34 +19,47 @@ package org.springframework.web.context.support; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; +import org.springframework.context.annotation.AnnotationConfigCapableApplicationContext; import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; import org.springframework.context.annotation.ScopeMetadataResolver; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; +import org.springframework.web.context.ContextLoader; /** - * {@link org.springframework.web.context.WebApplicationContext} implementation - * which accepts annotated classes as input - in particular + * {@link org.springframework.web.context.WebApplicationContext WebApplicationContext} + * implementation which accepts annotated classes as input - in particular * {@link org.springframework.context.annotation.Configuration @Configuration}-annotated - * classes, but also plain {@link org.springframework.stereotype.Component @Components} - * and JSR-330 compliant classes using {@code javax.inject} annotations. Allows for - * registering classes one by one (specifying class names as config location) as well + * classes, but also plain {@link org.springframework.stereotype.Component @Component} + * classes and JSR-330 compliant classes using {@code javax.inject} annotations. Allows + * for registering classes one by one (specifying class names as config location) as well * as for classpath scanning (specifying base packages as config location). * *
This is essentially the equivalent of * {@link org.springframework.context.annotation.AnnotationConfigApplicationContext} * for a web environment. * - *
To make use of this application context, the "contextClass" context-param for + *
To make use of this application context, the + * {@linkplain ContextLoader#CONTEXT_CLASS_PARAM "contextClass"} context-param for * ContextLoader and/or "contextClass" init-param for FrameworkServlet must be set to * the fully-qualified name of this class. * *
Unlike {@link XmlWebApplicationContext}, no default configuration class locations - * are assumed. Rather, it is a requirement to set the "contextConfigLocation" - * context-param for ContextLoader and/or "contextConfigLocation" init-param for + * are assumed. Rather, it is a requirement to set the + * {@linkplain ContextLoader#CONFIG_LOCATION_PARAM "contextConfigLocation"} + * context-param for {@link ContextLoader} and/or "contextConfigLocation" init-param for * FrameworkServlet. The param-value may contain both fully-qualified - * class names and base packages to scan for components. + * class names and base packages to scan for components. See {@link #loadBeanDefinitions} + * for exact details on how these locations are processed. + * + *
As an alternative to setting the "contextConfigLocation" parameter, users may + * implement an {@link org.springframework.context.ApplicationContextInitializer + * ApplicationContextInitializer} and set the + * {@linkplain ContextLoader#CONTEXT_INITIALIZER_CLASSES_PARAM "contextInitializerClasses"} + * context-param / init-param. In such cases, users should favor the {@link #refresh()} + * and {@link #scan(String...)} methods over the {@link #setConfigLocation(String)} + * method, which is primarily for use by {@code ContextLoader} * *
Note: In case of multiple {@code @Configuration} classes, later {@code @Bean} * definitions will override ones defined in earlier loaded files. This can be leveraged @@ -55,14 +68,20 @@ import org.springframework.util.StringUtils; * @author Chris Beams * @author Juergen Hoeller * @since 3.0 + * @see org.springframework.context.annotation.AnnotationConfigCapableApplicationContext * @see org.springframework.context.annotation.AnnotationConfigApplicationContext */ -public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext { +public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext + implements AnnotationConfigCapableApplicationContext { private Class>[] annotatedClasses; private String[] basePackages; + private BeanNameGenerator beanNameGenerator; + + private ScopeMetadataResolver scopeMetadataResolver; + /** * {@inheritDoc} *
This implementation accepts delimited values in the form of fully-qualified @@ -109,9 +128,11 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe } /** - * Set the annotated classes (typically {@code @Configuration} classes) - * for this web application context. + * {@inheritDoc} * @see #loadBeanDefinitions(DefaultListableBeanFactory) + * @see #register(Class...) + * @see #setConfigLocation(String) + * @see #refresh() */ public void register(Class>... annotatedClasses) { Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified"); @@ -119,8 +140,11 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe } /** - * Set the base packages to be scanned for annotated classes. + * {@inheritDoc} * @see #loadBeanDefinitions(DefaultListableBeanFactory) + * @see #register(Class...) + * @see #setConfigLocation(String) + * @see #refresh() */ public void scan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); @@ -212,6 +236,10 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe } } + public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) { + this.beanNameGenerator = beanNameGenerator; + } + /** * Provide a custom {@link BeanNameGenerator} for use with {@link AnnotatedBeanDefinitionReader} * and/or {@link ClassPathBeanDefinitionScanner}, if any. @@ -220,7 +248,11 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe * @see ClassPathBeanDefinitionScanner#setBeanNameGenerator */ protected BeanNameGenerator getBeanNameGenerator() { - return null; + return this.beanNameGenerator; + } + + public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) { + this.scopeMetadataResolver = scopeMetadataResolver; } /** @@ -231,7 +263,6 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe * @see ClassPathBeanDefinitionScanner#setScopeMetadataResolver */ protected ScopeMetadataResolver getScopeMetadataResolver() { - return null; + return this.scopeMetadataResolver; } - }