Hướng dẫn sử dụng @Lazy annotation trong Spring Boot

Mặc định, Spring sẽ khởi tạo tất cả các singleton bean tại thời điểm chương trình khởi chạy. Lý do đơn giản mà Spring làm như vậy để phát hiện ra các lỗi trong quá trình khởi tạo bean ngay lập tức mà không phải chờ đến thời điểm runtime.

Tuy nhiên, trong những trường hợp bạn không muốn khởi tạo một bean tại thời điểm khởi chạy chương trình mà chỉ khởi tạo ở lần đầu tiên chúng ta yêu cầu sử dụng. Chúng ta có thể làm được điều này với @Lazy annotation mà Spring cung cấp.

Lazy Initialization

@Lazy annotatition được giới thiệu từ phiên bản Spring 3.0, được dùng để chú thích các bean chỉ được khởi tạo ở lần đầu tiên được yêu cầu.

@Configuration class

Khi chúng ta chú thích @Lazy annotation trên một @Configuration class, nghĩa rằng tất cả các method được chú thích @Bean annotation bên trong sẽ được lazy-init (Chỉ khởi tạo tại lần đầu tiên được yêu cầu).

Ví dụ mình có một DataSource class chứa thông tin kết nối đến cơ sở dữ liệu.

public class DataSource {

    private String username;

    private String password;

    private String url;

    public DataSource() {
        System.out.println("DataSource bean is created");
    }

    // constructor, getter, setter
}

MyConfig class là một @Configuration class khởi tạo một DataSource Bean dùng cho toàn bộ dự án

@Configuration
@Lazy
public class AppConfig {

    @Bean
    public DataSource dataSource() {
        DataSource datasource = new DataSource();
        datasource.setUsername("username");
        datasource.setPassword("password");
        datasource.setUrl("jdbc:mysql://202.20.84.206:3306/mydb");
        return datasource;
    }
}

Như vậy, DataSource bean sẽ được lazy-init, và nếu mình đơn phương khởi chạy ứng dụng 

@SpringBootApplication
public class LazyApplication {

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

Thì màn hình console sẽ hiện thị như sau

2020-12-24 15:56:00.253  INFO 22380 --- [           main] com.deft.lazy.LazyApplication            : Starting LazyApplication using Java 11.0.9 on DDES-0348 with PID 22380 (D:\learning\spring_tutorials\lazy\target\classes started by hai.tn in D:\learning\spring_tutorials\lazy)
2020-12-24 15:56:00.256  INFO 22380 --- [           main] com.deft.lazy.LazyApplication            : No active profile set, falling back to default profiles: default
2020-12-24 15:56:00.637  INFO 22380 --- [           main] com.deft.lazy.LazyApplication            : Started LazyApplication in 0.693 seconds (JVM running for 1.009)

Chúng ta đều thấy rằng không có một dòng chữ DataSource bean is created  được xuất ra màn hình, vì MyConfig đã được chú thích bởi @Lazy trước đó.

Nhưng mình thử sử dụng DataSource bean trong dự án để in ra thông tin usernamepassword

@SpringBootApplication
public class LazyApplication {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(LazyApplication.class, args);
        DataSource dataSource = applicationContext.getBean(DataSource.class);
        System.out.println(dataSource.getUsername() + " - " + dataSource.getPassword());
    }
}

Kết quả DataSource bean đã được khởi tạo.

DataSource bean is created
username - password

@Lazy với @Autowired và @Component

Để hiểu rõ phần này các bạn cần có kiến thức về @Autowired@Component annotation trong spring.

Để lazy-init bean với @Component@Autowired chúng ta cần chú thích @Lazy ở cả 2 chỗ.

@Lazy tại @Component class

@Lazy
@Component
public class City {
    public City() {
        System.out.println("City bean initialized");
    }
}

Và tại nơi tham chiếu

package com.deft.lazy;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
public class Region {

    @Lazy
    @Autowired
    private City city;

    public Region() {
        System.out.println("Region bean initialized");
    }

    public City getCityInstance() {
        return city;
    }
}

City bean chỉ thật sự được khởi tạo khi bạn gọi đến getCityInstance() method để lấy về City instance và sử dụng getName() để in ra tên thành phố.

package com.deft.lazy;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class LazyApplicationTests {

	@Autowired
	private Region region;

	@Test
	public void givenLazyAnnotation_whenAutowire_thenLazyBean() {
		City city = region.getCityInstance();
		System.out.println(city.getName());
	}

}
Region bean initialized
2020-12-24 16:27:02.302  INFO 12660 --- [           main] com.deft.lazy.LazyApplicationTests       : Started )

City bean initialized
HCM

Kết bài

Trong bài hướng dẫn nhanh này, chúng ta đã học những kiến ​​thức cơ bản về chú thích @Lazy của Spring. Nhưng hãy lưu ý khi sử dụng Lazy, thông thường những dự án lớn họ không thường sử dụng @Lazy vì mục đích kiểm tra tất cả các bean trong dự án thay vì tại runtime bị lỗi sẽ gây ảnh hưởng rất lớn.

Sau cùng, các bạn có thể tham khảo mã nguồn tại gitlab: Lazy

Nguồn tham khảo

https://www.baeldung.com/spring-lazy-annotation

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x