bean là gì

Bài ghi chép được sự được chấp nhận của người sáng tác Lê Chí Dũng

1. Bean là gì?

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

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

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.

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

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

Lúc này chỉ nên biết đơn giản và giản dị nhất là dùng @Component lên class là class cơ là 1 trong những bean.

Xem tăng nhiều việc thực hiện Spring bổng cao trên TopDev

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

Ngoài rời khỏi chúng ta cũng có thể tiếp tục nghe nói tới BeanFactory. Nó cũng đại loại như ApplicationContext, thay mặt đại diện mang đến Spring IoC container tuy nhiên ở tại mức cơ phiên bản. ApplicationContext thì ở tại 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,…

ApplicationContext

Khi phần mềm Spring chạy, Spring IoC container tiếp tục quét tước toàn cỗ packages, lần rời khỏi những bean và đi vào ApplicationContext. Cơ chế này đó là Component scan.

Cách lấy bean rời khỏi kể từ Context

Tất nhiên trước lúc lấy bean rời khỏi kể từ context thì nên đem context rồi. Câu chất vấn đưa ra là phát triển thành context ở đâu?

Đó là ngay lập tức loại chính thức công tác 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() sẽ return về một object ApplicationContext interface, thay mặt đại diện mang đến IoC container.

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

Chúng tao rất có thể kéo ra bean kể từ trên đây, sử dụng method getBean().

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

// Lấy rời khỏi bám theo 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);

3. Kĩ thuật inject bean nhập 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ì dựa vào vào Engine, vì thế bám theo Dependency injection thì tất cả chúng ta cần thiết inject Engine vào trong Car.

3.1. Sử dụng @Autowired

Chúng tao dùng annotation @Autowired để báo mang đến Spring biết tự động hóa lần và inject bean tương thích nhập đị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 đến Spring lần bean này phù phù hợp với Engine interface
    // Và mang 1 bean tương thích là ChinaEngine
    // Nó tương tự với = new ChinaEngine()
    @Autowired
    private final Engine engine;
}

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

3.2. Inject qua chuyện constructor hoặc setter

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

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

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

Hoặc sử dụng loại setter-based như sau. Spring Boot sau khoản thời gian tạo ra đoạn bean Car sẽ gọi tăng method setEngine() sau cơ.

@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 sử dụng setter nhằm inject thông thường sử dụng nhập tình huống dựa vào vòng, module A tùy theo 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 ra bean này trước. Vì thế, biện pháp là 1 trong những bean tiếp tục sử dụng constructor, một bean sử dụng setter như bên trên.

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

4.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 ra tăng class VNEngine có tính năng tương tự 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ả nhập IDE nữa.

ApplicationContext

Có thể hiểu bởi Spring Boot tiếp tục nhìn thấy nhì bean tương thích nhằm inject vào Car. Do cả hai VNEngine và ChinaEngine đều implements Engine, mà Car cần Engine nên ko biết nên lựa chọn cái này.

4.2. Giải pháp

Có nhì cơ hội xử lý yếu tố này. Thứ nhất là dùng @Primary đánh vết 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, nhập tình huống có khá nhiều bean tương thích nhập context.

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

Cách 2 là hướng đẫn rõ ràng thương hiệu bean (tên class) ví dụ được inject bằng @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ỉ việc có @Qualifier trước thương hiệu field cần thiết inject nhập là được.

3. Spring Bean Life Cycle

1.1. Bean life cycle

Trong bài bác trước tất cả chúng ta tiếp tục lần hiểu sơ lược về bean là gì, thời điểm hôm nay tất cả chúng ta tiếp tục chuồn thâm thúy rộng lớn tí nhé.

Vòng đời (life cycle) của bean được hiểu là kể từ khi bean được đưa đến cho đến khi bị tiêu diệt chuồn, sẽ sở hữu những sự khiếu nại (event) không giống nhau xẩy ra. Về vòng đời của bean rất có thể tế bào miêu tả vị sơ thiết bị sau.

Nhìn có vẻ như nhiều năm và khó khăn hiểu, tuy nhiên đại loại tiếp tục bao gồm công việc sau:

Xem thêm: hmm là gì

  • IoC container tạo ra bean bằng phương pháp gọi constructor (có thể inject những bean dependency nhập đây)
  • Gọi những setter method nhằm inject những bean nhập vị setter based injection
  • Các method khởi tạo ra không giống được gọi (không cần thiết quan hoài nhiều)
  • @PostConstructor được gọi
  • Init method được gọi

Sau cơ bean tiếp tục sẵn sàng hoạt động và sinh hoạt. Nếu tiếp sau đó bean ko sử dụng nữa thì nó sẽ tiến hành hủy:

  • Gọi @PreDestroy
  • Hủy bean tựa như các object thông thường

1.2. @PostConstructor và @PreDestroy

Đây là nhì sự kiện khá cần thiết với bean, chúng ta cũng có thể hook một method nhập cơ nhằm thực ganh đua khi sự kiện xảy ra:

  • @PostConstruct là sau khoản thời gian bean tiếp tục khởi tạo ra xong
  • @PreDestroy là trước lúc bean bị phá huỷ hủy

Chúng tao sử dụng nhì annotation bên trên lưu lại lên method này cơ, method cơ sẽ tiến hành tự động hóa gọi khi sự khiếu nại bean xẩy ra.

class Car {
    @Autowired
    private final Engine engine;
    
    @PostConstruct
    public void testRun() {
        engine.run();
        engine.stop();
    }
    
    @PreDestroy
    public void stopEngine() {
        engine.stop();
    }
}

Như code ví dụ bên trên, bản thân gắn @PostConstruct cho method testRun(). Method này được gọi khi bean Car được đưa đến và khởi tạo ra hoàn hảo. Và trước khi Car bị phá huỷ diệt, thì nên cần gọi stopEngine tương tự động như bên trên.

Dùng nhập thực tiễn thì nhì annotation bên trên thực hiện những trọng trách như:

  • @PostConstruct dùng nhằm tiến hành một số trong những task khi khởi tạo ra bean
  • @PreDestroy thực hiện nay những task nhằm lau chùi bean sau khi sử dụng xong

2. Các loại bean

Nói đúng ra thì gọi là những scope, phân loại dựa vào con số bean được đưa đến. Bean bao gồm đem 5 scope:

  • Singleton (mặc định): IoC container chỉ tạo ra trúng độc nhất 1 object kể từ class bean này
  • Prototype: return một bean object riêng lẻ cho từng chuyến dùng.
  • Request: tạo ra từng bean cho từng request
  • Session: tạo ra từng bean cho từng session
  • Global session: tạo ra từng bean cho từng global session (cái này không hiểu nhiều lắm)

Trong 5 scope bên trên tất cả chúng ta chỉ quan hoài cho tới nhì scope đầu. Thông thường những các bạn sẽ không nhiều vấp cho tới prototype bean, tuy nhiên tôi cũng ghi chép rời khỏi bên trên trên đây luôn luôn.

Đối với singleton bean thì ngoài cần thiết lưu lại gì không còn, nó là đem ấn định rồi. Còn nếu như muốn hướng đẫn một class là prototype bean thì dùng @Scope như sau.

@Component
@Scope("prototype")
class PrototypeBean {
    ...
}

Nói rõ ràng rộng lớn về prototype bean, ví dụ bean X được dùng vị nhì bean không giống là A, B:

  • Nếu X là singleton bean, thì có duy nhất một object X được đưa đến. A và B sử dụng công cộng X.
  • Nếu X là prototype bean, thì đem 2 X được đưa đến mang đến 2 bean không giống dùng là X mang đến A và X mang đến B.

3. Cách khái niệm bean

Có 3 cơ hội khái niệm class là 1 trong những bean:

  • Khai báo nhập tệp tin XML
  • Dùng annotation bên trên class
  • Dùng @Configuration và @Bean

Tùy từng tình huống ví dụ nhưng mà sử dụng mang đến tương thích. Ví dụ nhập series này bản thân ko bàn thâm thúy về thông số kỹ thuật bean vị XML (do Spring Boot sinh rời khỏi ko nên nhằm cấu hình).

3.1. Dùng XML, annotations

Nhưng đơn giản và giản dị, chúng ta cũng nên biết trước đó Spring sử dụng XML nhằm thông số kỹ thuật những bean như sau. Nó khá là vô cùng nên người tao sử dụng cách thứ hai hoặc là hơn.

<?xml version = "1.0" encoding = "UTF-8"?>

<beans xmlns = "http://www.springframework.org/schema/beans"
    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation = "http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
    <!-- Đây là bean Car -->
    <bean id="" class="Car" init-method="testRun">
        <!-- Cấu hình tính chất property mang đến bean -->
    </bean>
</beans>

Do cơ người tao mới nhất sử dụng cơ hội thông số kỹ thuật bean dựa vào những annotation như @Component. Cụ thể thì như bài bác trước đem thưa, chỉ việc tiến công dấu @Component lên bên trên class thì IoC tiếp tục biết và tạo ra bean kể từ class cơ.

@Component
public class Car {
    ...
}

Ngoài rời khỏi đem những annotations không giống ví dụ rộng lớn như @Service@Repository@Controller,… cũng bao gồm @Component, nên ứng dụng của bọn chúng cũng chính là tạo ra bean.

3.3. Dùng @Bean bên trong @Configuration

Cách này sử dụng mang đến tình huống bean cần thiết tiến hành nhiều thao tác phức tạp nhằm khởi tạo ra, hoặc có khá nhiều bean tương quan cùng nhau. Do cơ, chứ không khởi tạo ra riêng rẽ rẽ từng class là từng bean, thì gom công cộng những bean cần thiết khởi tạo ra lại cho vô class chứa chấp là @Configuration.

Thường thì những class tiến công dấu @Configuration có hậu tố là Config.

@Configuration
public class AppConfig {
    // Khởi tạo ra trước những logic phức tạp
    // cũng có thể quy ấn định trật tự khởi tạo ra bean vị `@Order`
    public AppConfig() {
        ...
    }

    @Bean
    public Car carBean() {
        return new Car();
    }
    
    @Bean
    public PasswordEncoder passwordEncoderBean() {
        return new BCryptPasswordEncoder();
    }
    
    // cũng có thể khái niệm nhiều bean không giống với @Bean
}

Khi Spring nhìn thấy class @Configuration, nó sẽ bị tạo ra bean của class này trước (do @Configuration cũng là @Component). Trong khi tạo ra thì những logic khởi tạo ra cũng khá được thực ganh đua, nhằm sẵn sàng sẵn sàng tạo ra các @Bean bên nhập.

Sau cơ Spring Boot tiếp tục lần những method được tiến công dấu @Bean bên trong @Configuration để tạo ra bean. Thông thường những bean dạng này cụt và return ngay lập tức object chứ không hề nên nhằm Spring Boot đưa đến.

Các bean cũng khá được đi vào ApplicationContext như thông thường.

Tuy nhiên, ko nên class này lưu lại cũng khá được tạo ra bean. Mà nên đem ĐK quy trình component scan của IoC nên nhìn thấy nó. Chúng tao tiếp tục chuồn tiếp về component scan ngay lập tức tại đây.

4. Component scan

4.1. Cách component scan hoạt động

Khi phần mềm Spring Boot chính thức chạy, thì nó sẽ bị lần không còn những class lưu lại là bean nhập công tác và tạo ra bean. Quá trình lần tìm tòi những bean này gọi là component scan.

Component scan tiếp tục lần toàn cỗ class ở package nằm trong cấp cho hoặc những package thấp hơn

Do cơ, class tiến công dấu @SpringBootApplication có chứa chấp main method được xem là điểm chính thức. Spring Boot tiếp tục lần kể từ package này (package gốc) lần xuống muốn tạo những bean.

src/main/java/
    com/tonghoangvu/demo/
        DemoApplication.java
        components/
            Engine.java
            ChinaEngine.java
            Car.java
        controllers/
            UserController.java

Do cấu tạo folder đem ấn định của Spring Boot nó thế, nên kể từ package gốc có DemoApplication.java là com.tonghoangvu.demo, nó sẽ bị tìm:

  • Các class nằm trong cấp cho, lần được DemoApplication class, tạo ra bean
  • Tìm xuống những package thấp rộng lớn như com.tonghoangvu.demo.components và com.tonghoangvu.demo.controllers, lần tăng được những class như ChinaEngineCarUserController (Engine.java là interface nhé).

Do cơ, đem ấn định từng class được khai báo là bean đều rất có thể được tìm ra.

4.2. Tùy chỉnh package lần kiếm

Trong tình huống chúng ta chỉ ham muốn Spring Boot lần những bean nhập một package ví dụ, ví dụ chỉ lần nhập thư mục components thì đem 2 cơ hội như sau.

// Cách 1 sử dụng @ComponentScan với cùng một hoặc nhiều string (cần đem {})
@ComponentScan("com.tonghoangvu.demo.components")

// Cách 2 tăng tính chất @SpringBootApplication scanBasePackages
@SpringBootApplication(scanBasePackages = {
    "com.tonghoangvu.demo.components",
    "com.tonghoangvu.demo.controllers"
})
public class DemoApplication {
    public static void main(String[] args) {
        ...
    }
}

Bài ghi chép thời điểm hôm nay cho tới đó là đoạn, cũng coi như thể chuồn ngay gần không còn phần lý thuyết của Spring Boot rồi.

Xem thêm: name nghĩa là gì

Bài ghi chép gốc được đăng lên bên trên lcdung.top

Có thể chúng ta quan tiền tâm:

  • ReactJS – Tìm hiểu về Component Life Cycle
  • Gọi những object của Autowired Collections bám theo trật tự nhập Spring Framework
  • Giải mến React Component Lifecycle

Xem tăng Việc thực hiện IT hấp dẫn trên TopDev