3. Using @Configuration classes

3.1.  Bootstrapping applications with JavaConfigApplicationContext

JavaConfigApplicationContext provides direct access to the beans defined by @Configuration-annotated classes. For more information on the ApplicationContext API in general, please refer to the Core Spring documentation.

3.1.1. Construction Options

Instantiating the JavaConfigApplicationContext can be done by supplying @Configuration class literals to the constructor, and/or strings representing packages to scan for @Configuration classes.

3.1.1.1. Construction by class literal

Each of the class literals supplied to the constructor will be processed, and for each @Bean method encountered, JavaConfig will create a bean definition and ultimately instantiate and initialize the bean.

JavaConfigApplicationContext context = new JavaConfigApplicationContext(AppConfig.class);
Service service = context.getBean(Service.class);
                    

Passing multiple @Configuration classes:

JavaConfigApplicationContext context =
    new JavaConfigApplicationContext(AppConfig.class, DataConfig.class);
Service service = context.getBean(Service.class);
                    

3.1.1.2. Construction by base package

Base packages will be scanned for the existence of any @Configuration classes. Any candidate classes will then be processed much as if they had been supplied directly as class literals to the constructor.

JavaConfigApplicationContext context =
    new JavaConfigApplicationContext("com.acme.app.configuration");
Service service = context.getBean(Service.class);
                    

Passing multiple base packages:

JavaConfigApplicationContext context =
    new JavaConfigApplicationContext("com.acme.configuration", "com.acme.other");
Service service = context.getBean(Service.class);
                    

Matching packages and classes by wildcard:

JavaConfigApplicationContext context =
    new JavaConfigApplicationContext("**/configuration/**/*.class", "**/other/*Config.class");
Service service = context.getBean(Service.class);
                    

[Note]Note

The wildcard syntax for matching packages and classes above is based on Ant Patterns

3.1.1.3. Post-construction configuration

When one or more classes/packages are supplied as constructor arguments, a JavaConfigApplicationContext instance cannot be further configured. If post-construction configuration is preferred or required, use either the no-arg constructor, configure by calling setters, then manually refresh the context. After the call to refresh(), the context will be 'closed for configuration'.

JavaConfigApplicationContext context = new JavaConfigApplicationContext();
context.setParent(otherConfig);
context.setConfigClasses(AppConfig.class, DataConfig.class);
context.setBasePackages("com.acme.configuration");
context.refresh();
Service service = (Service) context.getBean("serviceA");
                    

[Note]Note

Whenever multiple packages and/or classes are used to instantiate a JavaConfigApplicationContext, order matters. This is important when considering what happens if two configuration classes define a bean with the same name. The last-specified class wins.

3.1.2. Accessing beans with getBean()

JavaConfigApplicationContext provides several variants of the getBean() method for accessing beans.

3.1.2.1. Type-safe access

The preferred method for accessing beans is with the type-safe getBean() method.

JavaConfigApplicationContext context = new JavaConfigApplicationContext(...);
Service service = context.getBean(Service.class);
                    

Disambuguation options

If more than one bean of type Service had been defined in the example above, the call to getBean() would have thrown an exception indicating an ambiguity that the container could not resolve. In these cases, the user has a number of options for disambiguation:

Indicating a @Bean as primary

Like Spring's XML configuration, JavaConfig allows for specifying a given @Bean as primary:

@Configuration
public class MyConfig {
    @Bean(primary=Primary.TRUE)
    public Service myService() {
        return new Service();
    }

    @Bean
    public Service backupService() {
        return new Service();
    }
}
                            

After this modification, all calls to getBean(Service.class) will return the primary bean

JavaConfigApplicationContext context = new JavaConfigApplicationContext(...);
Service service = context.getBean(Service.class); // returns the myService() primary bean
                            

Disambiguation by bean name

JavaConfig provides a getBean() variant that accepts both a class and a bean name for cases just such as these.

JavaConfigApplicationContext context = new JavaConfigApplicationContext(...);
Service service = context.getBean(Service.class, "myService");
                            

Because bean ids must be unique, this call guarantees that the ambiguity cannot occur.

Retrieve all beans of a given type

It is also reasonable to call the getBeansOfType() method in order to return all beans that implement a given interface:

JavaConfigApplicationContext context = new JavaConfigApplicationContext(...);
Map matchingBeans = context.getBeansOfType(Service.class);
                            

Note that this latter approach is actually a feature of the Core Spring Framework's AbstractApplicationContext (which JavaConfigApplicationContext extends) and is not type-safe, in that the returned Map is not parameterized.

3.1.2.2. String-based access

Beans may be accessed via the traditional string-based getBean() API as well. Of course this is not type-safe and requires casting, but avoids any potential ambiguity entirely:

JavaConfigApplicationContext context = new JavaConfigApplicationContext(...);
Service service = (Service) context.getBean("myService");