bean là gì

1. Bean và ApplicationContext là gì?

1.1. Bean là gì?

Trong documentation của Spring framework, thì bean được khái niệm như sau:

In Spring, the objects that size the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and otherwise managed by a Spring IoC container.

Bạn đang xem: bean là gì

Nói một cơ hội giản dị, bean là những module chủ yếu của lịch trình, được đưa đến và vận hành bởi vì Spring IoC container.

Các bean rất có thể dựa vào cho nhau, như ví dụ về Car, EngineChinaEngine từ trên đầu series cho tới giờ. Sự dựa vào này được tế bào mô tả mang lại IoC biết nhờ chế độ Dependency injection.

Cách lưu lại class là 1 trong những bean thì bản thân tiếp tục trình diễn vô bài bác tiếp sau. Lúc này chúng ta chỉ cần phải biết giản dị nhất là người sử dụng @Component lên class là class cơ là 1 trong những bean.

1.2. ApplicationContext là gì?

ApplicationContext là định nghĩa Spring Boot dùng làm chỉ Spring IoC container, tương tự động như bean là đại diện thay mặt cho những dependency.

Ngoài đi ra chúng ta cũng có thể tiếp tục nghe nói đến BeanFactory. Nó cũng đại loại như ApplicationContext, đại diện thay mặt mang lại Spring IoC container tuy nhiên ở tầm mức cơ bạn dạng. ApplicationContext thì ở tầm mức cao hơn nữa, cung ứng nhiều tác dụng rộng lớn BeanFactory như i18n, resolving messages, publishing events,...

Khi phần mềm Spring chạy, Spring IoC container tiếp tục quét dọn toàn cỗ packages, dò xét đi ra những bean và đi vào ApplicationContext. Cơ chế này đó là Component scan, cũng sẽ tiến hành thưa cho tới vô bài bác tiếp sau.

1.3. Cách lấy bean đi ra kể từ Context

Tất nhiên trước lúc lấy bean đi ra kể từ context thì cần đem context rồi 😦 Câu căn vặn đề ra là phát triển thành context ở đâu?

Đó là tức thì loại chính thức lịch trình Spring Boot. Câu mệnh lệnh sau.

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

Dòng method SpringApplication.run() tiếp tục return về một object ApplicationContext interface, đại diện thay mặt mang lại IoC container.

ApplicationContext context = SpringApplication.run(Application.class, args);

Chúng tao rất có thể lôi ra bean kể từ phía trên, người sử dụng method getBean().

// Lấy đi ra bean đem class cụ thể
Car xế hộp = context.getBean(Car.class);

// Lấy đi ra theo đòi thương hiệu và class
// Tuy là Engine.class tuy nhiên Engine lại là interface
Engine engine = context.getBean("ChinaEngine", Engine.class);

2. Kĩ thuật inject bean vô bean khác

Ví dụ chúng ta đem nhị bean là CarEngine (như ví dụ từ trên đầu series cho tới giờ). Và Car thì tùy thuộc vào Engine, vì thế theo đòi Dependency injection thì tất cả chúng ta cần thiết inject Engine vô vào Car.

Xem thêm: incidence là gì

2.1. Sử dụng @Autowired

Chúng tao dùng annotation @Autowired nhằm báo mang lại Spring biết tự động hóa dò xét và inject bean thích hợp vô địa điểm đặt điều annotation. Ví dụ.

// Annotation chỉ lưu lại lên class
public interface Engine {
    void run();
}
@Component
public class ChinaEngine implements Engine {
    @Override
    public void run() {}
}
@Component
public class Car {
    // Báo mang lại Spring dò xét bean này phù phù hợp với Engine interface
    // Và mang 1 bean thích hợp là ChinaEngine
    // Nó tương tự với = new ChinaEngine()
    @Autowired
    private final Engine engine;
}

Cách người sử dụng @Autowired bên trên field là ko được khuyến nghị, tự nó dùng Java reflection nhằm inject. Chúng tao nên suy nghĩ thay đổi qua loa người sử dụng inject theo phong cách constructor hoặc setter.

2.2. Inject qua loa constructor hoặc setter

Code inject theo phong cách constructor-based nên người sử dụng Khi những module là cần thiết. Khi cơ Spring Boot Khi tạo nên bean (cũng đơn giản tạo nên object, gọi constructor thôi) thì tiếp tục trả những tùy thuộc vào constructor Khi gọi.

Ví dụ class Car và đã được sửa lại nhằm inject Engine vô qua loa constructor.

@Component
public class Car {
    private final Engine engine;
    
    // Các bạn dạng Spring Boot mới mẻ thì ko cần thiết @Autowired bên trên constructor
    public Car(Engine engine) {
        this.engine = engine;
    }
}

Hoặc người sử dụng loại setter-based như sau. Spring Boot sau khoản thời gian tạo nên hoàn thành bean Car tiếp tục gọi thêm thắt method setEngine() tiếp sau đó.

@Component
public class Car {
    private final Engine engine;
    
    // Thêm @Required nhằm setter luôn luôn được gọi nhằm inject
    @Required
    public void setEngine(Engine engine) {
        this.engine = engine;
    }
}

Cách người sử dụng setter nhằm inject thông thường người sử dụng vô tình huống dựa vào vòng, module A tùy thuộc vào B và ngược lại. Do cơ, nếu như cả nhị đều dùng constructor based injection thì Spring Boot sẽ không còn biết nên tạo nên bean này trước. Vì thế, biện pháp là 1 trong những bean tiếp tục người sử dụng constructor, một bean người sử dụng setter như bên trên.

3. Khi Spring Boot ko biết lựa chọn bean nào?

3.1. Khi nhìn thấy nhiều bean phù hợp

Cũng lấy ví dụ bên trên, nếu như tất cả chúng ta tạo nên thêm thắt class VNEngine đem tính năng tương tự động ChinaEngine.

@Component
public class VNEngine implements Engine {
    @Override
    public void run() {}
}

Thì Spring Boot tiếp tục báo lỗi như sau (báo Khi chạy và cả vô IDE nữa.

Có thể hiểu tự Spring Boot đang được nhìn thấy nhị bean thích hợp nhằm inject vô Car. Do cả nhị VNEngineChinaEngine đều implements Engine, nhưng mà Car cần thiết Engine nên ko biết nên lựa chọn hình mẫu này.

3.2. Giải pháp

Có nhị cơ hội xử lý yếu tố này. Thứ nhất là người sử dụng @Primary lưu lại lên một bean. Khi cơ bean này sẽ tiến hành ưu tiên lựa chọn rộng lớn, vô tình huống có tương đối nhiều bean thích hợp vô context.

Xem thêm: unfr là gì

@Component
@Primary
public class VNEngine implements Engine {
    ...
}

Cách 2 là chỉ định và hướng dẫn rõ ràng thương hiệu bean (tên class) rõ ràng được inject bởi vì @Qualifier.

@Component
public class Car {
    @Autowired
    @Qualifier("VNEngine")  // Phải khớp hoa thông thường luôn luôn nhe
    private final Engine engine;
}

Đối với constructor hoặc setter based cũng tương tự động, chỉ cần phải có @Qualifier trước thương hiệu field cần thiết inject vô là được.


Okay thế là nội dung bài viết thời điểm ngày hôm nay đang được hoàn thành. Hai nội dung bài viết về bean và context của tôi mong muốn tiếp tục mang về mang lại chúng ta đầy đủ những kỹ năng và kiến thức cơ bạn dạng nhằm cút tiếp những phần sau của series. Cảm ơn và ghi nhớ upvote hoặc clip nhằm cỗ vũ bản thân nhé. Thân!