Spring Series - Spring Container

Photo by lucas Favre on Unsplash

Spring Series - Spring Container

What is a Spring Container?

Spring applications have a special data structure called the Spring Container(container for short). The objects that are managed by this container are called Spring-managed beans or components. The container does three critical tasks.

  1. Create

  2. Manage the Spring-managed beans

  3. Configure and resolve the dependencies between components

It is also important to note that, not all objects are inside the Spring container and there can be several objects outside the Spring container, such as strings.

Start Container

As we discussed in the previous article, when we generated a new Spring Boot project with the name Demo, the Spring Initializr generated a class named, DemoApplication with a main(..) method. And, in the body of the main(...) method, there is run(…) call, which starts up the container.

@SpringBootApplication
public class DemoApplication{
    public static void main(String args[]){
        SpringApplication.run(DemoApplication.class, args);
    }    
}

This run(…) method is a static method of the SpringApplication class. As shown above, two arguments have been passed to the run(…) method: the initial configuration, which is the type of your class, and the arguments passed to the main(…) method. If these arguments weren’t passed, Spring wouldn’t be able to get the arguments we pass on the command line.

Alternate Ways to Start Container

Rather than using the static run(…) method, we can also create an object of SpringApplication and later use the run(…) method. With this, we are capable of adding some settings to the SpringApplication object.

@SpringBootApplication
public class DemoApplication{
    public static void main(String args[]){
        SpringApplication app = new SpringApplication(DemoApplication.class);
        app.setHeadless(false);
        app.setBannerMode(Banner.Mode.OFF);
        app.setLogStartupInfo(false);
        // More initializations
        app.run(args);
    }
}

Rather than creating a SpringApplication object, we can use the SpringApplicationBuilder to create our SpringApplication object by following the builder pattern as well.

@SpringBootApplication
public class DemoApplication{
    public static void main(String args[]){
        new SpringApplicationBuilder(DemoApplication.class)
            .headless()
            .bannerMode(Banner.Mode.OFF)
            .logStartupInfo(false)
            .run(args);
    }
}

Although both of these alternatives look similar, there are two small differences.

  1. With SpringApplicationBuilder, you can only set states, you cannot read them, meaning there are no getters. However, in SpringApplication there are setters and getters, but the getters are rarely needed.

  2. In SpringApplicaionBuilder, hierarchical contexts can be set. In a hierarchical context, parents, children, and siblings can be modeled to have an isolated container.

Application Context

The run(…) method returns an application context, which represents the Spring container that holds all the beans created by the application. This can be stored in a variable and used later.

ConfigurableApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);

This ConfigurableApplicationContext is an interface that extends other interfaces.

We can also use ApplicationContext interface as well. The advantage of defining this kind of variable is that we are able to use the context methods defined in those interfaces. For instance, if we want to get a sorted list of all registered components, we can use the ApplicationContext as shown below.

ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
Arrays.stream(ctx.getBeanDefinitionNames())
    .sorted()
    .forEach(System.out::println);

Spring Boot Auto-Configuration

This feature is the main difference between Spring Boot and Spring Framework. With Spring Framework, we have to configure everything, but with Spring Boot components are automatically registered thanks to auto-configuration. For example, our application, DemoApplication is automatically instantiated as an object and placed in the container. Also, it is automatically named, in lowercase and not capitalized like the class name(demoApplication).

Interface ConfigurableApplicationContext extends ListableBeanFactory. And ListableBeanFactory extends BeanFactory. In there, we can find methods for taking Spring-managed beans and for existence tests.

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        DemoApplication bean = ctx.getBean(DemoApplication.class);
    }
}

This may either return the bean or an exception if the bean cannot be provided.

So this is it regarding Spring Container. In the next article, we’ll check about Picking Up Spring-Managed Beans through Class Path Scanning.