Spring源码解析之Bean的生命周期
在 Spring 容器启动时,会加载配置文件中的 bean 定义信息并通过反射机制创建 bean 实例,然后将这些 bean 实例化、初始化,最后将这些 bean 注册到 Spring 容器中,供外部调用。这个过程就是 Spring 容器管理 bean 的生命周期。在本文中,我们将探索 Spring 容器如何管理 bean 的生命周期。
1. bean 的生命周期
bean 的生命周期经过以下阶段:
- 实例化 (Instantiation)
- 属性赋值 (Populate properties)
- 初始化 (Initialization)
- 销毁 (Destruction)
下面我们将介绍这些阶段。
1.1 实例化
根据 bean 配置信息,Spring 容器会使用反射机制实例化一个 bean 对象。可以使用构造函数实例化对象,也可以使用工厂方法实例化对象。例如,下面的配置使用构造函数实例化对象:
<bean id="exampleBean" class="com.example.ExampleBean"/>
可以使用工厂方法实例化对象:
<bean id="exampleBean" factory-method="createInstance" class="com.example.ExampleBeanFactory"/>
其中,ExampleBeanFactory
是一个工厂类,createInstance
是工厂类中的工厂方法。
1.2 属性赋值
在实例化 bean 后,Spring 容器会调用 setter 方法设置 bean 的属性值。可以通过 XML 配置文件、Java 配置方式或自动扫描等方式进行属性注入。例如,下面的配置设置属性值:
<bean id="person" class="com.example.Person">
<property name="name" value="张三" />
<property name="age" value="20" />
</bean>
在上面的配置中,Person
类有两个属性 name
和 age
,通过 <property>
元素设置属性值。
1.3 初始化
在属性赋值完成后,Spring 容器会调用 InitializingBean
接口中的 afterPropertiesSet()
方法或 @PostConstruct
注解标注的方法执行 bean 的初始化。可以在初始化方法中完成一些准备工作。例如,下面的代码是一个初始化方法:
public class ExampleBean implements InitializingBean {
private String name;
private int age;
...
@Override
public void afterPropertiesSet() throws Exception {
// 执行初始化操作
...
}
}
或者,使用 @PostConstruct
注解标注初始化方法:
public class ExampleBean {
private String name;
private int age;
...
@PostConstruct
public void init() {
// 执行初始化操作
...
}
}
1.4 销毁
在容器关闭时,Spring 容器会调用 DisposableBean
接口中的 destroy()
方法或 @PreDestroy
注解标注的方法销毁 bean。
例如,下面的代码是销毁方法的示例:
public class ExampleBean implements DisposableBean {
private String name;
private int age;
...
@Override
public void destroy() throws Exception {
// 执行销毁操作
...
}
}
或者,使用 @PreDestroy
注解标注销毁方法:
public class ExampleBean {
private String name;
private int age;
...
@PreDestroy
public void destroy() {
// 执行销毁操作
...
}
}
2. 示例说明
我们通过示例来说明 bean 生命周期的过程。
首先,在 src/main/java/com/example
目录下新建 Person.java
文件,内容如下:
package com.example;
public class Person {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void sayHello() {
System.out.println("Hello, I'm " + name + ", " + age + " years old.");
}
}
然后,在 src/main/resources
目录下新建 applicationContext.xml
文件,内容如下:
<bean id="person" class="com.example.Person">
<property name="name" value="张三" />
<property name="age" value="20" />
</bean>
接下来,在 src/main/java/com/example
目录下新建 Main.java
文件,内容如下:
package com.example;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = context.getBean("person", Person.class);
person.sayHello();
((ClassPathXmlApplicationContext) context).close();
}
}
运行 Main
类,控制台输出:
Hello, I'm 张三, 20 years old.
在这个示例中,Person
类有两个属性 name
和 age
,在 applicationContext.xml
中通过 <property>
元素设置属性值。在 Main
类中,通过 ApplicationContext
加载 applicationContext.xml
配置文件,并从中获取 Person
实例,调用 sayHello()
方法输出信息。在程序结束时,使用 close()
方法关闭容器,销毁 bean。
除了 XML 配置方式,还可以使用注解方式或 Java 配置方式构建 bean。例如,下面的代码是使用注解方式构建 bean:
package com.example;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class ExampleBean {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@PostConstruct
public void init() {
System.out.println("Initializing ExampleBean...");
}
@PreDestroy
public void destroy() {
System.out.println("Destroying ExampleBean...");
}
}
使用 Java 配置方式构建 bean:
package com.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
public ExampleBean exampleBean() {
return new ExampleBean();
}
}
我们可以在项目中使用不同的方式来构建 bean,并了解它们的生命周期信息,从而更好地理解 Spring 容器对 bean 的管理。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring源码解析之Bean的生命周期 - Python技术站