Explore Amazon Deals

「Spring Boot #1」 Guide to @Component and @Autowired

Introduction:

This is an introductory article about two fundamental annotations in Spring Boot: @Component and @Autowired. To understand this section better, it's essential to grasp the following two concepts:

  1. The concept of tight-coupling and loosely coupled
  2. Explanation of Dependency Injection (DI) and IoC

Installation:

You can install Spring Boot library packages in Maven by adding the spring-boot-starter-parent as the parent of the entire project:

        <parent>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-parent</artifactid>
            <version>3.2.1</version>
            <relativepath> <!--lookup parent from repository-->
            </relativepath>
        </parent>

And to add libraries for web programming or server-side development, we add:

      
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
      
    

pom.xml

      
        <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <parent>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>3.2.1</version>
                <relativePath/> <!-- lookup parent from repository -->
            </parent>
            <groupId>com.blogspot.amztopfind</groupId>
            <artifactId>spring-boot-tutorial</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <packaging>pom</packaging>
            <name>spring-boot-tutorial</name>
            <description>Everything about Spring Boot</description>
            <properties>
                <java.version>21</java.version>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </dependency>
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-maven-plugin</artifactId>
                    </plugin>
                </plugins>
            </build>
        </project>
      
    

Folder Structure:

Component-Autowired

How to run a Spring Boot application.

In traditional Java, when running an entire project, we have to define a main() function and set it to execute first.

Similarly, in Spring Boot, we need to specify where it should initiate for the first run to set up everything.

This is accomplished by adding the @SpringBootApplication annotation to the main class and calling SpringApplication.run(App.class, args); to run the project.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

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

Reading about Dependency Injection (DI) and IoC, you'll understand that one of the primary tasks of Spring is to create a Container to hold Dependencies for us.

SpringApplication.run(App.class, args) is precisely the command to create this container. It then scans all dependencies in your project and puts them inside.

Spring names this container as ApplicationContext and labels the dependencies inside as Beans.

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        // "ApplicationContext" contains all dependencies within the project.
        ApplicationContext context = SpringApplication.run(App.class, args);
    }
}

So, how does Spring know which one is a dependency? That's where the concept of @Component comes in.

@Component is an Annotation marked on Classes to help Spring recognize that it is a Bean.

Example:

We have an interface called Outfit.

      
public interface Outfit {
    public void wear();
}

Implement it with the class Bikini.

      
/*
Mark the class with @Component
This class will be understood by Spring Boot as a Bean (or dependency)
And will be managed by Spring Boot
*/
@Component
public class Bikini implements Outfit {
    @Override
    public void wear() {
        System.out.println("Wear bikini");
    }
}

Run the program and observe the result:

      
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        // The ApplicationContext is the container that holds all the Beans.
        ApplicationContext context = SpringApplication.run(App.class, args);

        // After running, the context will contain Beans marked with @Component.

        // Retrieve a Bean by
        Outfit outfit = context.getBean(Outfit.class);

        // Print to see what it is
        System.out.println("Instance: " + outfit);
        // Use the wear() method
        outfit.wear();
    }
}

Output:

  • [1] Instance: com.blogspot.amztopfind.helloword.Bikini@6951842
  • [2] Wear bikini.
  • You will see that the Outfit now is indeed a Bikini. The class has been marked as @Component.
  • When Spring Boot runs, it scans all classes at the same level or in lower packages compared to the App class you provide to Spring (We can configure this search, which will be discussed later). During this scanning process, when it encounters a class marked with @Component, it creates an instance and places it into the ApplicationContext for management.

  • The running process will be as follows:

  • Component-Autowired


  • Component-Autowired

    @Autowired:

    Now, let's create a Girl class with a property named Outfit.

    I also mark Girl as a @Component. This means Spring Boot needs to create an instance of Girl for management.

      
@Component
public class Girl {

    @Autowired
    Outfit outfit;

    public Girl(Outfit outfit) {
        this.outfit = outfit;
    }
    
    // GET 
    // SET
}

I mark the Outfit property of Girl with the @Autowired Annotation. This tells Spring Boot to automatically inject an instance of Outfit into this property when initializing Girl.

Now, try running the program.

      
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        // The ApplicationContext is the container that holds all the Beans.
        ApplicationContext context = SpringApplication.run(App.class, args);

        // After running, the context will contain Beans marked with @Component.

        // Retrieving a Bean
        Outfit outfit = context.getBean(Outfit.class);

        // Print to see what it is
        System.out.println("Output Instance: " + outfit);
        // Using the wear() method
        outfit.wear();

        // Retrieving another Bean
        Girl girl = context.getBean(Girl.class);

        // Printing the Girl bean instance
        System.out.println("Girl Instance: " + girl);

        // Printing the Outfit associated with the Girl
        System.out.println("Girl Outfit: " + girl.outfit);

        // Using the wear() method of the outfit associated with the Girl
        girl.outfit.wear();
    }
}

Output:

  • [1] Output Instance: com.blogspot.amztopfind.helloword.Bikini@6951842
  • [2] Wear bikini.
  • [3] Girl Instance: com.blogspot.amztopfind.helloword.Girl@2ced5f67
  • [4] Girl Outfit: com.blogspot.amztopfind.helloword.Bikini@6951842
  • [5] Wear bikini.
  • [6] true
  • Spring Boot automatically creates a Girl, and during the creation process, it injects Outfit as a property.

    Singleton:

    An important point is that all Beans managed within ApplicationContext are singletons. You may have noticed this from the outputs above.

    • [1] Output Instance: com.blogspot.amztopfind.helloword.Bikini@6951842
    • [4] Girl Outfit: com.blogspot.amztopfind.helloword.Bikini@6951842

    The Outfit in the two objects is the same.

    All Beans managed within ApplicationContext are created only once, and when a Class requires @Autowired, it takes the available object from ApplicationContext to inject.

    In case you want a completely new instance every time you use it, then mark that @Component with @Scope("prototype").

      
@Component
@Scope("prototype")
public class Bikini implements Outfit {
    @Override
    public void wear() {
        System.out.println("Wear bikini");
    }
}

Conclusion:

By now, you have gained an understanding of the two most fundamental concepts in Spring Boot, which are also its core foundation. Understanding how @Component and @Autowired operate means you've already covered half the journey.

Next Post Previous Post
No Comment
Add Comment
comment url