- Sản phẩm & Dịch vụSản phẩm & Dịch vụ
- Giải phápGiải pháp
- Bảng giáBảng giá
- Công tyCông ty
- Tài liệuTài liệu
vi
vi
Chuyên mục với các bài viết hướng dẫn, nghiên cứu và phân tích chi tiết về kỹ thuật, các xu hướng công nghệ mới nhất dành cho lập trình viên.
Technical Writer
I have over 5 years of experience writing technical documentation for tech products, making them accessible and user-friendly. My focus is always on providing clear and precise information. @#@ Tôi đã có hơn 5 năm kinh nghiệm viết tài liệu kỹ thuật cho các sản phẩm công nghệ, giúp người dùng dễ dàng tiếp cận và sử dụng. Tôi luôn tập trung vào việc cung cấp thông tin chính xác và dễ hiểu.
Thảo luận (0)
Đăng nhập để thảo luận
Hôm nay, chúng ta sẽ tìm hiểu về vòng đời của Spring Bean. Spring Beans là phần quan trọng nhất trong bất kỳ ứng dụng Spring nào. ApplicationContext của Spring chịu trách nhiệm khởi tạo các Bean đã được định nghĩa trong tập tin cấu hình Spring.

Spring Context cũng chịu trách nhiệm tiêm (inject) các phụ thuộc (dependencies) vào bean, thông qua setter, constructor hoặc sử dụng spring autowiring. Đôi khi, chúng ta muốn khởi tạo một số tài nguyên trong class của bean, ví dụ như thiết lập kết nối cơ sở dữ liệu hoặc xác thực các dịch vụ bên thứ ba ngay khi khởi tạo trước khi có bất kỳ yêu cầu nào từ phía client. Spring framework cung cấp nhiều cách để khai báo các phương thức sau khởi tạo (post-initialization) và trước hủy (pre-destroy) trong vòng đời của một bean.
InitializingBean và định nghĩa phương thức afterPropertiesSet(). Đối với trước khi hủy, chúng ta triển khai DisposableBean và định nghĩa phương thức destroy(). Đây là các phương thức callback, tương tự như các servlet listener. Cách tiếp cận này đơn giản nhưng không được khuyến khích vì nó khiến bean phụ thuộc chặt chẽ vào Spring framework.Lưu ý: Cả hai phương thức post-init và pre-destroy không nên có tham số, nhưng vẫn có thể ném ra Exception. Ngoài ra, bạn cần lấy instance của bean từ Spring ApplicationContext để gọi các phương thức này.
Spring framework cũng hỗ trợ các annotation @PostConstruct và @PreDestroy để định nghĩa các phương thức hậu khởi tạo và trước khi hủy. Các annotation này thuộc package javax.annotation. Tuy nhiên, để các annotation này hoạt động, chúng ta cần cấu hình ứng dụng Spring để tìm kiếm annotation. Chúng ta có thể làm điều này bằng cách khai báo một bean có kiểu org.springframework.context.annotation.CommonAnnotationBeanPostProcessor hoặc bằng phần tử context: annotation-config trong file cấu hình Spring Bean. Hãy viết một ứng dụng Spring đơn giản để trình bày cách sử dụng các cấu hình trên trong việc quản lý vòng đời của Spring Bean. Tạo một dự án Maven Spring trong Spring Tool Suite, dự án hoàn chỉnh sẽ trông giống như hình dưới đây.

Chúng ta không cần thêm bất kỳ phụ thuộc nào bổ sung để cấu hình các phương thức vòng đời của Spring Bean, file pom.xml của chúng ta giống như bất kỳ dự án Spring Maven tiêu chuẩn nào khác.
<project xmlns="<https://maven.apache.org/POM/4.0.0>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>" xsi:schemaLocation="<https://maven.apache.org/POM/4.0.0> <https://maven.apache.org/xsd/maven-4.0.0.xsd>"> <modelVersion>4.0.0</modelVersion> <groupId>org.springframework.samples</groupId> <artifactId>SpringBeanLifeCycle</artifactId> <version>0.0.1-SNAPSHOT</version><properties>
<!-- Generic properties --> <java.version>1.7</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Spring --> <spring-framework.version>4.0.2.RELEASE</spring-framework.version> <!-- Logging --> <logback.version>1.0.13</logback.version> <slf4j.version>1.7.5</slf4j.version> </properties> <dependencies> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring-framework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring-framework.version}</version> </dependency> <!-- Logging with SLF4J & LogBack --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> <scope>runtime</scope> </dependency> </dependencies></project>
Tạo một Java Bean đơn giản để được sử dụng trong các service class.
package com.journaldev.spring.bean;public class Employee {
private String name; public String getName() { return name; } public void setName(String name) { this.name = name; }}
Tạo một class service để triển khai cả hai interface trên cho các phương thức post-init và pre-destroy.
package com.journaldev.spring.service;import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean;
import com.journaldev.spring.bean.Employee;
public class EmployeeService implements InitializingBean, DisposableBean{
private Employee employee; public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public EmployeeService(){ System.out.println("EmployeeService no-args constructor called"); } @Override public void destroy() throws Exception { System.out.println("EmployeeService Closing resources"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("EmployeeService initializing to dummy value"); if(employee.getName() == null){ employee.setName("Pankaj"); } }}
Vì chúng ta không muốn các service của mình phụ thuộc trực tiếp vào Spring Framework, hãy tạo một phiên bản khác của lớp EmployeeService, trong đó chúng ta sẽ định nghĩa các phương thức vòng đời của Spring post-init và pre-destroy, và sẽ cấu hình chúng trong file cấu hình Spring Bean.
package com.journaldev.spring.service;import com.journaldev.spring.bean.Employee;
public class MyEmployeeService{
private Employee employee; public Employee getEmployee() { return employee; } public void setEmployee(Employee employee) { this.employee = employee; } public MyEmployeeService(){ System.out.println("MyEmployeeService no-args constructor called"); } //pre-destroy method public void destroy() throws Exception { System.out.println("MyEmployeeService Closing resources"); } //post-init method public void init() throws Exception { System.out.println("MyEmployeeService initializing to dummy value"); if(employee.getName() == null){ employee.setName("Pankaj"); } }}
Chúng ta sẽ xem xét file cấu hình Spring Bean sau một chút. Trước đó, hãy tạo một lớp service khác sử dụng các annotation @PostConstruct và @PreDestroy.
Dưới đây là một lớp đơn giản sẽ được cấu hình như một Spring Bean, và cho các phương thức post-init và pre-destroy, chúng ta sử dụng các chú thích @PostConstruct và @PreDestroy.
package com.journaldev.spring.service;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;
public class MyService {
@PostConstruct public void init(){ System.out.println("MyService init method called"); } public MyService(){ System.out.println("MyService no-args constructor called"); } @PreDestroy public void destory(){ System.out.println("MyService destroy method called"); }}
Hãy xem cách chúng ta cấu hình các bean trong file context của Spring.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="<https://www.springframework.org/schema/beans>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>" xsi:schemaLocation="<https://www.springframework.org/schema/beans> <https://www.springframework.org/schema/beans/spring-beans.xsd>"><!-- Not initializing employee name variable--> <bean name="employee" class="com.journaldev.spring.bean.Employee" />
<bean name="employeeService" class="com.journaldev.spring.service.EmployeeService"> <property name="employee" ref="employee"></property> </bean>
<bean name="myEmployeeService" class="com.journaldev.spring.service.MyEmployeeService" init-method="init" destroy-method="destroy"> <property name="employee" ref="employee"></property> </bean>
<!-- initializing CommonAnnotationBeanPostProcessor is same as context:annotation-config --> <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" /> <bean name="myService" class="com.journaldev.spring.service.MyService" /> </beans>
Lưu ý rằng tôi không khởi tạo tên nhân viên trong định nghĩa bean của nó. Vì EmployeeService đang sử dụng interface nên chúng ta không cần bất kỳ cấu hình đặc biệt nào ở đây. Với bean MyEmployeeService, chúng ta sử dụng thuộc tính init-method và destroy-method để cho Spring Framework biết các phương thức tùy chỉnh cần thực thi. Cấu hình bean MyService không có gì đặc biệt, nhưng như bạn thấy, tôi đang bật cấu hình dựa trên annotation cho nó. Ứng dụng của chúng ta đã sẵn sàng, hãy viết một chương trình kiểm thử để xem các phương thức khác nhau được thực thi như thế nào.
package com.journaldev.spring.main;import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.service.EmployeeService; import com.journaldev.spring.service.MyEmployeeService;
public class SpringMain {
public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); System.out.println("Spring Context initialized"); //MyEmployeeService service = ctx.getBean("myEmployeeService", MyEmployeeService.class); EmployeeService service = ctx.getBean("employeeService", EmployeeService.class); System.out.println("Bean retrieved from Spring Context"); System.out.println("Employee Name="+service.getEmployee().getName()); ctx.close(); System.out.println("Spring Context Closed"); }}
Khi chạy chương trình test trên, bạn sẽ thấy kết quả sau.
Apr 01, 2014 10:50:50 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@c1b9b03: startup date [Tue Apr 01 22:50:50 PDT 2014]; root of context hierarchy Apr 01, 2014 10:50:50 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [spring.xml] EmployeeService no-args constructor called EmployeeService initializing to dummy value MyEmployeeService no-args constructor called MyEmployeeService initializing to dummy value MyService no-args constructor called MyService init method called Spring Context initialized Bean retrieved from Spring Context Employee Name=Pankaj Apr 01, 2014 10:50:50 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@c1b9b03: startup date [Tue Apr 01 22:50:50 PDT 2014]; root of context hierarchy MyService destroy method called MyEmployeeService Closing resources EmployeeService Closing resources Spring Context Closed
Bạn có thể bỏ ghi chú dòng code tạo bean kiểu MyEmployeeService để kiểm chứng các điểm trên cũng áp dụng tương tự.
Đôi khi chúng ta cần các đối tượng của Spring Framework trong các bean để thực hiện một số thao tác, ví dụ như đọc các tham số ServletConfig và ServletContext hoặc để biết các định nghĩa bean được nạp bởi ApplicationContext. Đó là lý do Spring Framework cung cấp một loạt các interface dạng *Aware mà chúng ta có thể implement trong các lớp bean của mình. org.springframework.beans.factory.Aware là interface đánh dấu gốc cho tất cả các interface *Aware này. Tất cả các interface *Aware đều là các sub-interface của Aware và khai báo một phương thức setter duy nhất để bean implement. Sau đó, Spring context sử dụng dependency injection theo kiểu setter để tiêm các đối tượng tương ứng vào bean và làm cho chúng sẵn sàng cho chúng ta sử dụng. Các interface Aware của Spring tương tự như các servlet listener với các phương thức callback và thực hiện theo mẫu thiết kế observer. Một số interface Aware quan trọng gồm có:
package com.journaldev.spring.service;import java.util.Arrays;
import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ImportAware; import org.springframework.core.env.Environment; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.AnnotationMetadata;
public class MyAwareService implements ApplicationContextAware, ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware, BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware {
@Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { System.out.println("setApplicationContext called"); System.out.println("setApplicationContext:: Bean Definition Names=" + Arrays.toString(ctx.getBeanDefinitionNames())); } @Override public void setBeanName(String beanName) { System.out.println("setBeanName called"); System.out.println("setBeanName:: Bean Name defined in context=" + beanName); } @Override public void setBeanClassLoader(ClassLoader classLoader) { System.out.println("setBeanClassLoader called"); System.out.println("setBeanClassLoader:: ClassLoader Name=" + classLoader.getClass().getName()); } @Override public void setResourceLoader(ResourceLoader resourceLoader) { System.out.println("setResourceLoader called"); Resource resource = resourceLoader.getResource("classpath:spring.xml"); System.out.println("setResourceLoader:: Resource File Name=" + resource.getFilename()); } @Override public void setImportMetadata(AnnotationMetadata annotationMetadata) { System.out.println("setImportMetadata called"); } @Override public void setEnvironment(Environment env) { System.out.println("setEnvironment called"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("setBeanFactory called"); System.out.println("setBeanFactory:: employee bean singleton=" + beanFactory.isSingleton("employee")); } @Override public void setApplicationEventPublisher( ApplicationEventPublisher applicationEventPublisher) { System.out.println("setApplicationEventPublisher called"); }}
Tập tin cấu hình Spring bean rất đơn giản.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="<https://www.springframework.org/schema/beans>" xmlns:xsi="<https://www.w3.org/2001/XMLSchema-instance>" xsi:schemaLocation="<https://www.springframework.org/schema/beans> <https://www.springframework.org/schema/beans/spring-beans.xsd>"><bean name="employee" class="com.journaldev.spring.bean.Employee" />
<bean name="myAwareService" class="com.journaldev.spring.service.MyAwareService" />
</beans>
package com.journaldev.spring.main;import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.service.MyAwareService;
public class SpringAwareMain {
public static void main(String[] args) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-aware.xml"); ctx.getBean("myAwareService", MyAwareService.class); ctx.close(); }}
Bây giờ khi chúng ta thực thi lớp ở trên, chúng ta sẽ nhận được kết quả sau.
Apr 01, 2014 11:27:05 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@60a2f435: startup date [Tue Apr 01 23:27:05 PDT 2014]; root of context hierarchy Apr 01, 2014 11:27:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [spring-aware.xml] setBeanName called setBeanName:: Bean Name defined in context=myAwareService setBeanClassLoader called setBeanClassLoader:: ClassLoader Name=sun.misc.Launcher$AppClassLoader setBeanFactory called setBeanFactory:: employee bean singleton=true setEnvironment called setResourceLoader called setResourceLoader:: Resource File Name=spring.xml setApplicationEventPublisher called setApplicationContext called setApplicationContext:: Bean Definition Names=[employee, myAwareService] Apr 01, 2014 11:27:05 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@60a2f435: startup date [Tue Apr 01 23:27:05 PDT 2014]; root of context hierarchy
Kết quả hiển thị trên bảng điều khiển của chương trình kiểm thử khá dễ hiểu, vì vậy tôi sẽ không đi vào chi tiết. Đó là tất cả về các phương thức vòng đời của Spring Bean và cách tiêm các đối tượng đặc thù của framework vào các Spring Bean. Vui lòng tải dự án mẫu từ liên kết bên dưới và phân tích để tìm hiểu thêm về chúng.
Tải xuống Dự án Vòng đời Spring Bean