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
, Engine
và ChinaEngine
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à Car
và Engine
(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ị VNEngine
và ChinaEngine
đề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!
Bình luận