Blog Spring Boot

Understanding Spring Annotations: @ComponentScan, @Configuration, and @EnableAutoConfiguration

In this blog post, we’ll dive into some of the core annotations used in Spring Framework: @ComponentScan, @Configuration, and @EnableAutoConfiguration.

@ComponentScan

The @ComponentScan annotation is used by Spring to automatically detect the beans. It tells Spring where to search for components that should be managed by the Spring container. When you use @ComponentScan, Spring scans the specified package(s) and registers all the components (classes annotated with @Component, @Service, @Repository, @Controller, etc.) as beans in the ApplicationContext.

Java
@Configuration
@ComponentScan("com.example.myapp.services")
public class AppConfig {
}

In this example, Spring will scan the com.example.myapp.services package and all its sub-packages for components.

@Configuration

The @Configuration annotation in Spring is used to indicate that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        // instantiate, configure and return bean ...
    }
}

In the above example, myBean() is an instance of MyBean class. This instance will be automatically managed by Spring Container.

@EnableAutoConfiguration

The @EnableAutoConfiguration annotation tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. It simplifies the configuration by automatically configuring your Spring application based on the dependencies you have added in the pom.xml file.

@EnableAutoConfiguration
public class ExampleMain {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(ExampleMain.class, args);
    }
}

Practical Example

Let’s see how these annotations work together in a practical example. Suppose we have a service class MyService:

Java
@Service
public class MyService {
    public String sayHello(){
        return "Hello, my service";
    }
}

We can use Spring’s @Autowired annotation to automatically inject an instance of MyService into another class, like this:

Java
@Component
public class MyApp {
    private final MyService myService;

    @Autowired
    public MyApp(MyService myService){
        this.myService = myService;
    }
    public void run(){
        System.out.println(myService.sayHello());
    }
}

In this example, MyApp is a Spring-managed component that depends on MyService. Because MyService is also a Spring-managed component (thanks to @ComponentScan), Spring can automatically inject an instance of MyService into MyApp when it’s created.

Now, to call the run() method of MyApp after the Spring application starts, you can do it like this in your main application class:

Java
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);

        MyApp myApp = context.getBean(MyApp.class);
        myApp.run();
    }
}

In this code, SpringApplication.run(DemoApplication.class, args) starts the Spring application and returns an instance of ConfigurableApplicationContext. Then, we get the MyApp bean from the application context and call the run() method.

Difference between @EnableAutoConfiguration and @ComponentScan

Sure, I can explain the difference between @EnableAutoConfiguration and @ComponentScan and provide examples where one would not be able to do the work of the other.

@EnableAutoConfiguration: This annotation tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. It’s part of Spring Boot’s convention-over-configuration approach and is designed to reduce the configuration required for a Spring application. For example, if you have a spring-webmvc on your classpath and you haven’t manually configured any ViewResolver beans, then @EnableAutoConfiguration will automatically configure one for you.

The “class path settings” mentioned in the description of @EnableAutoConfiguration refer to these dependencies that you’ve added to your project and which are available on the classpath when your application runs.

It’s important to note that @EnableAutoConfiguration doesn’t add these dependencies for you. You need to add them yourself in your pom.xml or build.gradle file. What @EnableAutoConfiguration does is to auto-configure various beans and settings based on these dependencies.

@ComponentScan: This annotation tells Spring where to look for components, configurations, and services. It scans the specified package(s) and registers all the components (classes annotated with @Component, @Service, @Repository, @Controller, etc.) as beans in the ApplicationContext.

    Here’s an example where @ComponentScan is necessary and @EnableAutoConfiguration is not enough:

    Java
    package com.example.myapp.services;
    
    import org.springframework.stereotype.Service;
    
    @Service
    public class MyService {
        public String sayHello() {
            return "Hello, Spring!";
        }
    }
    

    In this case, even if you use @EnableAutoConfiguration, Spring won’t be able to find MyService unless you also use @ComponentScan to tell Spring to scan the com.example.myapp.services package.

    On the other hand, here’s an example where @EnableAutoConfiguration is necessary and @ComponentScan is not enough:

    package com.example.myapp;
    
    import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class MyController {
    
        @GetMapping("/")
        public String home() {
            return "Hello, Spring!";
        }
    }
    

    In this case, even if you use @ComponentScan, the home() method won’t be mapped to the “/” URL unless you also use @EnableAutoConfiguration, which among other things, sets up Spring MVC with a DispatcherServlet to handle incoming web requests.

    For example, if you have spring-boot-starter-web in your pom.xml@EnableAutoConfiguration sets up defaults like a DispatcherServlet (to handle incoming web requests), a Tomcat server (to serve your application), and Jackson (for JSON conversion), among other things.

    Similarly, if you have spring-boot-starter-data-jpa in your pom.xml@EnableAutoConfiguration sets up defaults like a Hibernate EntityManagerFactory and a DataSource.

    However, it’s important to note that @EnableAutoConfiguration doesn’t handle all possible configurations. It’s designed to work with a wide range of applications, but there might be certain specific configurations that you need to set up manually.

    So, while there is some overlap in what @EnableAutoConfiguration and @ComponentScan do, they each have their own responsibilities and are both necessary for a fully functioning Spring Boot application.

    Conclusion

    These annotations are part of the core framework which makes Spring Boot a rapid application development platform. The combination of these annotations and the embedded HTTP servers (like Tomcat, Jetty or Undertow) makes Spring Boot a convenient choice for microservice-based applications.


    I hope you find this blog post helpful! If you have any questions or need further clarification, feel free to ask. 😊

    Avatar

    Neelabh

    About Author

    As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

    You may also like

    Blog Design Pattern

    Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

    Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
    Blog Tech Toolkit

    Base64 Decode

    Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over