Instantiating the Infra Container by Using AnnotationConfigApplicationContext

The following sections document Infra AnnotationConfigApplicationContext, introduced in Infra 3.0. This versatile ApplicationContext implementation is capable of accepting not only @Configuration classes as input but also plain @Component classes and classes annotated with JSR-330 metadata.

When @Configuration classes are provided as input, the @Configuration class itself is registered as a bean definition and all declared @Bean methods within the class are also registered as bean definitions.

When @Component and JSR-330 classes are provided, they are registered as bean definitions, and it is assumed that DI metadata such as @Autowired or @Inject are used within those classes where necessary.

Simple Construction

In much the same way that Infra XML files are used as input when instantiating a ClassPathXmlApplicationContext, you can use @Configuration classes as input when instantiating an AnnotationConfigApplicationContext. This allows for completely XML-free usage of the Infra container, as the following example shows:

  • Java

public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
  MyService myService = ctx.getBean(MyService.class);
  myService.doStuff();
}

As mentioned earlier, AnnotationConfigApplicationContext is not limited to working only with @Configuration classes. Any @Component or JSR-330 annotated class may be supplied as input to the constructor, as the following example shows:

  • Java

public static void main(String[] args) {
  ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
  MyService myService = ctx.getBean(MyService.class);
  myService.doStuff();
}

The preceding example assumes that MyServiceImpl, Dependency1, and Dependency2 use Infra dependency injection annotations such as @Autowired.

Building the Container Programmatically by Using register(Class<?>…​)

You can instantiate an AnnotationConfigApplicationContext by using a no-arg constructor and then configure it by using the register() method. This approach is particularly useful when programmatically building an AnnotationConfigApplicationContext. The following example shows how to do so:

  • Java

public static void main(String[] args) {
  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppConfig.class, OtherConfig.class);
  ctx.register(AdditionalConfig.class);
  ctx.refresh();
  MyService myService = ctx.getBean(MyService.class);
  myService.doStuff();
}

Enabling Component Scanning with scan(String…​)

To enable component scanning, you can annotate your @Configuration class as follows:

  • Java

@Configuration
@ComponentScan(basePackages = "com.acme") (1)
public class AppConfig  {
  // ...
}
1 This annotation enables component scanning.

Experienced Infra users may be familiar with the XML declaration equivalent from Infra context: namespace, shown in the following example:

<beans>
  <context:component-scan base-package="com.acme"/>
</beans>

In the preceding example, the com.acme package is scanned to look for any @Component-annotated classes, and those classes are registered as Infra bean definitions within the container. AnnotationConfigApplicationContext exposes the scan(String…​) method to allow for the same component-scanning functionality, as the following example shows:

  • Java

public static void main(String[] args) {
  AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.scan("com.acme");
  ctx.refresh();
  MyService myService = ctx.getBean(MyService.class);
}
Remember that @Configuration classes are meta-annotated with @Component, so they are candidates for component-scanning. In the preceding example, assuming that AppConfig is declared within the com.acme package (or any package underneath), it is picked up during the call to scan(). Upon refresh(), all its @Bean methods are processed and registered as bean definitions within the container.

Support for Web Applications with AnnotationConfigWebApplicationContext

A WebApplicationContext variant of AnnotationConfigApplicationContext is available with AnnotationConfigWebApplicationContext. You can use this implementation when configuring the Infra ContextLoaderListener mockApi listener, Web MVC MockDispatcher, and so forth. The following web.xml snippet configures a typical Web MVC web application (note the use of the contextClass context-param and init-param):

<web-app>
  <!-- Configure ContextLoaderListener to use AnnotationConfigWebApplicationContext
    instead of the default XmlWebApplicationContext -->
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>
      cn.taketoday.web.context.support.AnnotationConfigWebApplicationContext
    </param-value>
  </context-param>

  <!-- Configuration locations must consist of one or more comma- or space-delimited
    fully-qualified @Configuration classes. Fully-qualified packages may also be
    specified for component-scanning -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.acme.AppConfig</param-value>
  </context-param>

  <!-- Bootstrap the root application context as usual using ContextLoaderListener -->
  <listener>
    <listener-class>cn.taketoday.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- Declare a Web MVC DispatcherServlet as usual -->
  <mockApi>
    <mockApi-name>dispatcher</mockApi-name>
    <mockApi-class>cn.taketoday.web.mockApi.DispatcherServlet</mockApi-class>
    <!-- Configure DispatcherServlet to use AnnotationConfigWebApplicationContext
      instead of the default XmlWebApplicationContext -->
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>
        cn.taketoday.web.context.support.AnnotationConfigWebApplicationContext
      </param-value>
    </init-param>
    <!-- Again, config locations must consist of one or more comma- or space-delimited
      and fully-qualified @Configuration classes -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>com.acme.web.MvcConfig</param-value>
    </init-param>
  </mockApi>

  <!-- map all requests for /app/* to the dispatcher mockApi -->
  <mockApi-mapping>
    <mockApi-name>dispatcher</mockApi-name>
    <url-pattern>/app/*</url-pattern>
  </mockApi-mapping>
</web-app>
For programmatic use cases, a GenericWebApplicationContext can be used as an alternative to AnnotationConfigWebApplicationContext. See the GenericWebApplicationContext javadoc for details.