Xem thêm

Giới thiệu về Component Scan trong Spring Boot

Huy Erick
Hình ảnh: 「Spring Boot #5」 Component Scan là gì? Trong thiết kế Layer của Spring Boot, chúng ta đã được biết đến với 2 trong số 3 Annotation cơ bản, đó là @Component, @Service, và...

「Spring Boot #5」 Component Scan là gì? Hình ảnh: 「Spring Boot #5」 Component Scan là gì?

Trong thiết kế Layer của Spring Boot, chúng ta đã được biết đến với 2 trong số 3 Annotation cơ bản, đó là @Component, @Service, và @Repository. Tuy nhiên, bạn đã bao giờ tìm hiểu về cách Spring Boot tìm kiếm Bean trong project của bạn chưa?

Trong bài viết này, chúng ta sẽ tìm hiểu về khái niệm "Component Scan" trong Spring Boot và cách thức nó hoạt động.

Cài đặt

Để sử dụng Component Scan trong Spring Boot, ta cần thiết lập Maven file (pom.xml) như sau:

<?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 Spring Boot

Component Scan có nghĩa là khi chạy Spring Boot, nó 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 các Bean từ những Class mà nó tìm thấy.

Xem ví dụ sau đây:

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

@Component
public class OtherGirl {
    @Override
    public String toString() {
        return "OtherGirl.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");
        }
    }
}

Kết quả khi chạy chương trình sẽ là cả 2 bean "Girl" và "OtherGirl" được tạo ra trong Context. Điều này chứng tỏ Spring Boot đã tự động tìm kiếm các Bean bên cạnh class App và các package con bên cạnh App.

Tuỳ chỉnh Component Scan

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, bạn có thể sử dụng các cách sau đây:

Cách 1: Sử dụng @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: Sử dụng 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ả hai cách trên đều cho kết quả là "Bean Girl không tồn tại" và "Bean: OtherGirl.java". Điều này chứng tỏ Spring Boot chỉ tìm kiếm các bean trong package "others" mà thôi.

Quét nhiều package

Nếu bạn muốn cấu hình cho Spring Boot tìm kiếm các Bean ở nhiều package khác nhau, bạn có thể sử dụng các cách sau đây:

@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"})

Kết

Đây là một bài viết trong Series làm chủ Spring Boot, từ zero to hero.

Như mọi khi, mã nguồn được đăng tải trên Github.

1