Introduce AnnotationConfigWAC #scan and #register

Primarily for use in conjunction with ApplicationContextInitializer,
these new #scan and #register methods mirror those in
AnnotationConfigApplicationContext. #setConfigLocation
and #setConfigLocations methods remain for compatibility with
ContextLoader-style initialization, but have been locally overridden
and documented clearly.

AnnotationConfigWebApplicationContext#loadBeanDefinitions Javadoc has
also been updated to explain the processing logic for each of these
potential inputs.

Issue: SPR-8320
master
Chris Beams 14 years ago
parent 56720fc42c
commit e128ee2464
  1. 112
      org.springframework.web/src/main/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContext.java
  2. 22
      org.springframework.web/src/test/java/org/springframework/web/context/support/AnnotationConfigWebApplicationContextTests.java

@ -16,12 +16,14 @@
package org.springframework.web.context.support;
import org.springframework.beans.factory.config.BeanDefinition;
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.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScopeMetadataResolver;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* {@link org.springframework.web.context.WebApplicationContext} implementation
@ -57,14 +59,92 @@ import org.springframework.context.annotation.ScopeMetadataResolver;
*/
public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext {
private Class<?>[] annotatedClasses;
private String[] basePackages;
/**
* {@inheritDoc}
* <p>This implementation accepts delimited values in the form of fully-qualified
* class names, (typically of {@code Configuration} classes) or fully-qualified
* packages to scan for annotated classes. During {@link #loadBeanDefinitions}, these
* locations will be processed in their given order, first attempting to load each
* value as a class. If class loading fails (i.e. a {@code ClassNotFoundException}
* occurs), the value is assumed to be a package and scanning is attempted.
* <p>Note that this method exists primarily for compatibility with Spring's
* {@link org.springframework.web.context.ContextLoader} and that if this application
* context is being configured through an
* {@link org.springframework.context.ApplicationContextInitializer}, use of the
* {@link #register} and {@link #scan} methods are preferred.
* @see #register(Class...)
* @see #scan(String...)
* @see #setConfigLocations(String[])
* @see #loadBeanDefinitions(DefaultListableBeanFactory)
*/
@Override
public void setConfigLocation(String location) {
super.setConfigLocation(location);
}
/**
* {@inheritDoc}
* <p>This implementation accepts individual location values as fully-qualified class
* names (typically {@code @Configuration} classes) or fully-qualified packages to
* scan. During {@link #loadBeanDefinitions}, these locations will be processed in
* order, first attempting to load values as a class, and upon class loading failure
* the value is assumed to be a package to be scanned.
* <p>Note that this method exists primarily for compatibility with Spring's
* {@link org.springframework.web.context.ContextLoader} and that if this application
* context is being configured through an
* {@link org.springframework.context.ApplicationContextInitializer}, use of the
* {@link #register} and {@link #scan} methods are preferred.
* @see #scan(String...)
* @see #register(Class...)
* @see #setConfigLocation(String)
* @see #loadBeanDefinitions(DefaultListableBeanFactory)
*/
@Override
public void setConfigLocations(String[] locations) {
super.setConfigLocations(locations);
}
/**
* Set the annotated classes (typically {@code @Configuration} classes)
* for this web application context.
* @see #loadBeanDefinitions(DefaultListableBeanFactory)
*/
public void register(Class<?>... annotatedClasses) {
Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
this.annotatedClasses = annotatedClasses;
}
/**
* Set the base packages to be scanned for annotated classes.
* @see #loadBeanDefinitions(DefaultListableBeanFactory)
*/
public void scan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
this.basePackages = basePackages;
}
/**
* Register a {@link BeanDefinition} for each class specified by {@link #getConfigLocations()},
* or scan each specified package for annotated classes. Enables the default set of
* annotation configuration post processors, such that {@code @Autowired},
* {@code @Required}, and associated annotations can be used.
* <p>Configuration class bean definitions are registered with generated bean definition
* names unless the {@code value} attribute is provided to the stereotype annotation.
* @see #getConfigLocations()
* Register a {@link org.springframework.beans.factory.config.BeanDefinition} for
* any classes specified by {@link #register(Class...)} and scan any packages
* specified by {@link #scan(String...)}.
* <p>For any values specified by {@link #setConfigLocation(String)} or
* {@link #setConfigLocations(String[])}, attempt first to load each location as a
* class, registering a {@code BeanDefinition} if class loading is successful,
* and if class loading fails (i.e. a {@code ClassNotFoundException} is raised),
* assume the value is a package and attempt to scan it for annotated classes.
* <p>Enables the default set of annotation configuration post processors, such that
* {@code @Autowired}, {@code @Required}, and associated annotations can be used.
* <p>Configuration class bean definitions are registered with generated bean
* definition names unless the {@code value} attribute is provided to the stereotype
* annotation.
* @see #register(Class...)
* @see #scan(String...)
* @see #setConfigLocation()
* @see #setConfigLocations()
* @see AnnotatedBeanDefinitionReader
* @see ClassPathBeanDefinitionScanner
*/
@ -87,6 +167,22 @@ public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWe
scanner.setScopeMetadataResolver(scopeMetadataResolver);
}
if (!ObjectUtils.isEmpty(this.annotatedClasses)) {
if (logger.isInfoEnabled()) {
logger.info("Registering annotated classes: [" +
StringUtils.arrayToCommaDelimitedString(this.annotatedClasses) + "]");
}
reader.register(this.annotatedClasses);
}
if (!ObjectUtils.isEmpty(this.basePackages)) {
if (logger.isInfoEnabled()) {
logger.info("Scanning base packages: [" +
StringUtils.arrayToCommaDelimitedString(this.basePackages) + "]");
}
scanner.scan(this.basePackages);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
for (String configLocation : configLocations) {

@ -16,9 +16,9 @@
package org.springframework.web.context.support;
import static org.junit.Assert.*;
import org.junit.Test;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -28,8 +28,20 @@ import org.springframework.context.annotation.Configuration;
public class AnnotationConfigWebApplicationContextTests {
@Test
public void testSingleWellFormedConfigLocation() {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
public void registerSingleClass() {
AnnotationConfigWebApplicationContext ctx =
new AnnotationConfigWebApplicationContext();
ctx.register(Config.class);
ctx.refresh();
TestBean bean = ctx.getBean(TestBean.class);
assertNotNull(bean);
}
@Test
public void configLocationWithSingleClass() {
AnnotationConfigWebApplicationContext ctx =
new AnnotationConfigWebApplicationContext();
ctx.setConfigLocation(Config.class.getName());
ctx.refresh();
@ -41,7 +53,7 @@ public class AnnotationConfigWebApplicationContextTests {
@Configuration
static class Config {
@Bean
public TestBean testBean() {
public TestBean myTestBean() {
return new TestBean();
}
}

Loading…
Cancel
Save