Three Basic Concepts for your Java Spring Program

Beans, Components and Autowiring

Spring is the most popular Java framework, since it offers flexibility, scales well and can be configured for operations that have high security requirements. These are some of the advantages why Spring is often used by enterprises and Spring developers are in demand.

In this article I will familiarise you with three basic concepts that are a must to understand in your Spring learning journey:

1) @Bean

Beans are plain old java objects (the java objects you know and love) that are managed by the Spring IoC (Inversion of Control) container, a core part of the Spring framework.

Spring will instantiate, manage and ultimately discard the Bean objects without having the developer write repetitive boilerplate code and worrying about the control flow of the program or forgetting to instantiate objects.

Example:

//Initialization of a plain old java object (POJO)
public class Car {
    protected String name;

    String setName(String newName) {
    return this.name = newName;
    };
}
-----

public class Index {

    public static void main(String[] args) {

        Car car1 = new Car();
        car1.setName("Volkswagen");

        System.out.print("The name of the car from the POJO class is " + car1.name);    
    }
}

Did you notice how we created per hand the object car1? This can get very tedious once there are more objects of type car that we want to use.

The Spring framework instead injects the objects to the program per dependency injection(link). Every Spring project will need at least 3 classes: the class of the object you want to inject, the project configuration class and the main/index class.

In the example below the car1 variable gets injected into the main class (the car2 variable is just an example for another bean). It may seem at first like you need to write more code, but a good IDE like Eclipse or IntelliJ should automatically do the imports for you and help with autocompletion.

//Initialization by the Spring framework
package valerie.car.beans;

public class Car {

    protected String name;

    public void setName(String name) {
        this.name = name;
    }
}

package valerie.car.beans;

import valerie.car.beans.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class ProjectConfig {


    @Bean
    Car car1() {
        var myCar = new Car();
        car.setName("Volkswagen");
        return myCar;
    }

    @Bean
    Car car2() {
        var yourCar = new Car();
        car.setName("BMW");
        return yourCar;
    }

}

package valerie.car.main;

import valerie.car.beans.Car;
import valerie.car.config.ProjectConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Index {

    public static void main(String[] args) {


        var context = new AnnotationConfigApplicationContext(ProjectConfig.class);
        Car myCar = context.getBean("car1",Car.class);
        System.out.println("Car name from Spring Context is: " + car.getName());
    }
}

2) @Component

Components are so called stereotype annotations, therefore special beans and have three subtypes:

  • @Service: can be used for classes containing the business logic of your program or any methods for making external API calls.

  • @Repository: handles the code for classes concerned with data operations and data bases.

  • @Controller: can be used for structuring your code as an MVC pattern (further details on the MVC pattern are available here.

Components (and therefore also Services, Repositories and Controllers) can be added only once to a class in the Spring context program. They do not require as much code written by you as normal Beans but they also leave less control to you, the developer, as the Spring framework will take care of configuration.

While you cannot configure components right out of the box, you as a developer have some further annotations to your disposal for controling the component after initialization (for example by using the @PostConstruct annotation).

3) @Autowired

One of the complexities that arise in software/web development stem from objects delegating certain functionalities to other objects of a similar or another type. Usually in Java you will need to specify these dependencies directly in your objects. Spring offers a way to simplify this issue. Let's look at some code for demonstration:

//Taking the example from above, I wish to specify that my car is the Volkswagen.
//One way to specify this dependency could be as follows:
@Bean
    public Car car1() {
        var myCar = new Car();
        car.setName("Volkswagen");
        return myCar;
    }

@Bean
public Person person1() {
   Person person = new Person();
   person.setName("Valerie");
   person.setCar(car1);
   return person;

I therefore used a setter method directly in the Bean person to state the dependency that the person object (Valerie) has upon the car1 object (Volkswagen).

Using @Autowired though makes things much simpler:

@Component
   public class Person {

... private String name = "Valerie";
private final Car car;

//...
   @Autowired
   public Person(Car car) {
      System.out.println("Person created by Spring.");
      this.car = car;
   }

Let me know in the comments if you found this overview useful or have any questions.

Keep on learning!