Series Spring Boot từ con số 0

  1. Spring Boot 1: Hướng dẫn Component và Autowired
  2. Spring Boot 2: Autowired - Primary - Qualifier
  3. Spring Boot 3: Spring Bean Life Cycle + PostConstruct và PreDestroy
  4. Spring Boot 4: Component - Service - Repository
  5. Spring Boot 5 : Component Scan là gì?
  6. Spring Boot 6 : Configuration và Bean
  7. Spring Boot 7: Spring Boot Application Config và @Value
  8. Spring Boot 8 : Tạo Web Helloworld với @Controller + Thymeleaf
  9. Spring Boot 9: Giải thích cách Thymeleaf vận hành + Expression + Demo Full
  10. Spring Boot 10: @RequestMapping + @PostMapping + @ModelAttribute + @RequestParam + Web To-Do với Thymeleaf
  11. Spring Boot 11: Hướng dẫn Spring Boot JPA + MySQL
  12. Spring Boot 12: Spring JPA Method + @Query
  13. Spring Boot 13: [ Special ] Chi tiết Spring Boot + Thymeleaf + MySQL + i18n + Web Demo
  14. Spring Boot 14: Restful API + @RestController + @PathVariable + @RequestBody
  15. Spring Boot 15: Exception Handling @ExceptionHandler + @RestControllerAdvice / @ControllerAdvice + @ResponseStatus
  16. Spring Boot 16: Hướng dẫn sử dụng @ConfigurationProperties
  17. Spring Boot 17: Chạy nhiều môi trường với Spring Profile
  18. Spring Boot 18: Hướng dẫn chi tiết Test Spring Boot (P1)
  19. Spring Boot 19 : Hướng dẫn chi tiết Test Spring Boot (Phần 2)

Giới thiệu

Trong bài trước tôi đã đề cập tới: Spring Boot 4: Component - Service - Repository

Trong bài hôm này, chúng ta sẽ tìm hiểu thêm về cách Spring Boot tìm kiếm Bean trong project của bạn như thế nào.

Cài đặt

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>me.loda.spring</groupId>
    <artifactId>spring-boot-learning</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-boot-learning</name>
    <description>Everything about Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <!--spring mvc, rest-->
        <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>

Component Scan

Trong bài 1 tôi có đề cập một lần về việc Spring Boot khi chạy sẽ dò tìm toàn bộ các Class cùng cấp hoặc ở trong các package thấp hơn và tạo ra Bean từ các Class tìm thấy.

Bây giờ chúng ta sẽ nói sâu hơn một chút!

Thử ví dụ này nhé:

Chúng ta có một project có cấu trúc thư mục như này:

image

Tôi tạo ra 2 Bean:

  1. Girl. Nằm cùng package với App
  2. OtherGirl. Nằm ở package con othersothers cùng cấp với App

Girl.java

@Component
public class Girl {

    @Override
    public String toString() {
        return "Girl.java";
    }
}

OtherGirl.java

@Component
public class OtherGirl {
    @Override
    public String toString() {
        return "OtherGirl.java";
    }
}

App.java

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(App.class, args);
        try {
            Girl girl = context.getBean(Girl.class);
            System.out.println("Bean: " + girl.toString());
        } catch (Exception e) {
            System.out.println("Bean Girl không tồn tại");
        }

        try {
            OtherGirl otherGirl = context.getBean(OtherGirl.class);
            if (otherGirl != null) {
                System.out.println("Bean: " + otherGirl.toString());
            }
        } catch (Exception e) {
            System.out.println("Bean Girl không tồn tại");
        }
    }
}

Chạy chương trình:

Bean: Girl.java
Bean: OtherGirl.java

Kết quả in ra màn hình là cả 2 bean Girl và OtherGirl đều được tạo ra trong Context.

Điều này chứng tỏ Spring Boot đã đi tìm các Bean bên cạnh class App và những package con bên cạnh App

Component Scan

Trong trường hợp bạn muốn tuỳ chỉnh cấu hình cho Spring Boot chỉ tìm kiếm các bean trong một package nhất định thì có các cách sau đây:

  1. Sử dụng @ComponentScan
  2. Sử dụng scanBasePackages tromg @SpringBootApplication.

Cách 1: @ComponentScan

Sửa file App.java thành:

@ComponentScan("me.loda.spring.componentscan.others")
@SpringBootApplication
public class App {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(App.class, args);
        try {
            Girl girl = context.getBean(Girl.class);
            System.out.println("Bean: " + girl.toString());
        } catch (Exception e) {
            System.out.println("Bean Girl không tồn tại");
        }

        try {
            OtherGirl otherGirl = context.getBean(OtherGirl.class);
            if (otherGirl != null) {
                System.out.println("Bean: " + otherGirl.toString());
            }
        } catch (Exception e) {
            System.out.println("Bean Girl không tồn tại");
        }
    }
}

Cách 2: scanBasePackages

@SpringBootApplication(scanBasePackages = "me.loda.spring.componentscan.others")
public class App {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(App.class, args);
        try {
            Girl girl = context.getBean(Girl.class);
            System.out.println("Bean: " + girl.toString());
        } catch (Exception e) {
            System.out.println("Bean Girl không tồn tại");
        }

        try {
            OtherGirl otherGirl = context.getBean(OtherGirl.class);
            if (otherGirl != null) {
                System.out.println("Bean: " + otherGirl.toString());
            }
        } catch (Exception e) {
            System.out.println("Bean Girl không tồn tại");
        }
    }
}

Cả 2 cách đều cho kết quả in ra màn hình như sau:

Bean Girl không tồn tại
Bean: OtherGirl.java

Lúc này, Spring Boot chỉ tìm kiếm các bean trong package others mà thôi. Nên khi lấy ra Girl thì nó không tồn tại trong Context.

Multiple package scan

Bạn có thể cấu hình cho Spring Boot Tìm kiếm các Bean ở nhiều package khác nhau bằng cách:

@ComponentScan({"me.loda.spring.componentscan.others2","me.loda.spring.componentscan.others"})

hoặc

@SpringBootApplication(scanBasePackages = {"me.loda.spring.componentscan.others", "me.loda.spring.componentscan.others2"})

 

Bài viết kì tiếp theo: Spring Boot 6: Configuration và Bean


Bài viết nằm trong series Làm chủ Spring Boot, Zero to Hero

Bài viết được đăng tải lại dưới sự cho phép của tác giả - Thầy Nam là giảng viên Lộ trình Java Spring Boot Full Stack

Link gốc bài viết tại đây