spring bean的生命周期
1. Spring Bean的生命周期简介
Spring bean 的生命周期是指 Bean 在 Spring(IoC)中从创建到销毁的整个过程。
在Spring框架中,Bean的生命周期包括以下阶段:
- 实例化:通过构造函数或工厂方法创建Bean实例。
- 属性赋值:调用Bean实例的setter方法将属性值注入到Bean中。
- 初始化:执行Bean实例的初始化方法,例如init-method指定的方法。
- 使用:Bean实例被放入容器中供其他对象使用。
- 销毁:容器关闭时,销毁Bean实例,执行Bean实例的destroy-method指定的方法。
Spring框架提供了各种扩展点,使得用户可以对Bean的生命周期进行自定义处理,例如通过BeanPostProcessor接口来拓展初始化前后的操作,通过DisposableBean接口来定义销毁方法等。下面我们从这些扩展点入手,详细介绍Spring Bean的生命周期。
2. Spring Bean的实例化
Bean的实例化是指根据Bean定义创建一个实例对象的过程。具体来说,Bean的实例化分为以下两个阶段:
- BeanDefinition的加载和解析:在启动Spring容器时,容器会读取应用程序上下文配置文件或通过Java代码配置的BeanDefinition,并将其解析成spring内部数据结构,这些数据结构描述了Bean的元数据信息,如:类名、属性、依赖关系等信息。
- 实例化Bean对象:解析完成后,Spring容器使用Java反射机制创建Bean对象并初始化它们,同时注入所需的依赖项和属性值。通常情况下,Spring通过调用Bean的无参构造函数来创建实例对象。如果Bean的构造函数需要参数,则Spring将根据参数类型自动查找并注入所需的依赖项。
需要注意的是,在默认情况下,Spring使用单例模式创建Bean实例。也就是说,每个Bean定义只对应一个实例对象,所有从容器中获取该Bean的请求都将返回同一个实例。如果需要创建多个实例,可以通过配置作用域(scope)来实现
在实例化阶段,开发者还可以通过实现BeanPostProcessor接口的回调方法在Bean实例化前后进行一些自定义操作,例如修改Bean属性值、记录日志等。
关于spring bean的配置文件,通常使用XML配置,也可以使用java的@Configuration和@Bean注解。
Spring框架提供了三种方式来实例化Bean:
2.1 使用构造函数实例化Bean
使用构造函数实例化Bean是最常见的方式。在XML配置文件中,我们可以使用
<bean id="myBean" class="my.package.MyBean">
<constructor-arg name="arg1" value="value1"/>
<constructor-arg name="arg2" ref="refBean"/>
</bean>
在这个例子中,我们通过
2.2 使用静态工厂方法实例化Bean
使用静态工厂方法实例化Bean需要在XML配置文件中指定factory-method属性和factory-bean属性。例如:
<bean id="myBean" class="my.package.MyBeanFactory" factory-method="createBean">
<constructor-arg name="arg1" value="value1"/>
<constructor-arg name="arg2" ref="refBean"/>
</bean>
在这个例子中,我们指定了MyBeanFactory类中的createBean静态方法来实例化Bean,并且通过
2.3 使用实例工厂方法实例化Bean
使用实例工厂方法实例化Bean需要在XML配置文件中指定factory-method属性和factory-bean属性。不同的是,factory-bean属性需要指向一个已经存在于容器中的Bean实例,而不是一个类名。例如:
<bean id="myBeanFactory" class="my.package.MyBeanFactory"/>
<bean id="myBean" factory-bean="myBeanFactory" factory-method="createBean">
<constructor-arg name="arg1" value="value1"/>
<constructor-arg name="arg2" ref="refBean"/>
</bean>
在这个例子中,我们指定了MyBeanFactory类中的createBean方法来实例化Bean,并且通过factory-bean属性指定了MyBeanFactory类的实例。
3. Spring Bean的属性赋值
在Spring框架中,我们可以使用setter方法、构造函数来对Bean的属性进行赋值。其中,setter方法是最常用的方式。例如:
<bean id="myBean" class="my.package.MyBean">
<property name="prop1" value="value1"/>
<property name="prop2" ref="refBean"/>
</bean>
在这个例子中,我们通过
如果我们需要对一个List或Map等集合类型的属性进行赋值,可以使用或
<bean id="myBean" class="my.package.MyBean">
<property name="listProp">
<list>
<value>value1</value>
<value>value2</value>
</list>
</property>
<property name="mapProp">
<map>
<entry key="key1" value="value1"/>
<entry key="key2" value="value2"/>
</map>
</property>
</bean>
在这个例子中,我们使用和
4. Spring Bean的初始化
Spring框架提供了两种方式来执行Bean的初始化方法:
4.1 使用init-method指定初始化方法
可以在XML配置文件中使用init-method属性来指定Bean的初始化方法。例如:
<bean id="myBean" class="my.package.MyBean" init-method="init">
<property name="prop1" value="value1"/>
<property name="prop2" ref="refBean"/>
</bean>
在这个例子中,我们通过init-method属性指定了MyBean的初始化方法为init。
4.2 实现InitializingBean接口
还可以让Bean实现InitializingBean接口,并重写afterPropertiesSet()方法。例如:
public class MyBean implements InitializingBean {
private String prop1;
private RefBean prop2;
@Override
public void afterPropertiesSet() throws Exception {
// 初始化操作
}
// setter和getter方法省略
}
在这个例子中,我们让MyBean类实现了InitializingBean接口,并在afterPropertiesSet()方法中编写了初始化操作。
5. Spring Bean的使用
一旦Bean被实例化、属性赋值并初始化后,它就可以被放入容器中供其他对象使用了。例如:
<bean id="myService" class="my.package.MyService">
<property name="myBean" ref="myBean"/>
</bean>
在这个例子中,我们将MyBean注入到了MyService中的myBean属性中,并且将MyService放入了容器中供其他对象使用。
6. Spring Bean的销毁
在Spring框架中,我们可以使用destroy-method属性来指定Bean的销毁方法。例如:
<bean id="myBean" class="my.package.MyBean" destroy-method="destroy">
<property name="prop1" value="value1"/>
<property name="prop2" ref="refBean"/>
</bean>
在这个例子中,我们通过destroy-method属性指定了MyBean的销毁方法为destroy。
还可以让Bean实现DisposableBean接口,并重写destroy()方法。例如:
public class MyBean implements DisposableBean {
private String prop1;
private RefBean prop2;
@Override
public void destroy() throws Exception {
// 销毁操作
}
// setter和getter方法省略
}
在这个例子中,我们让MyBean类实现了DisposableBean接口,并在destroy()方法中编写了销毁操作。
7. Spring Bean的扩展点
除了上述介绍的Bean生命周期阶段,Spring框架还提供了各种扩展点,使得用户可以对Bean的生命周期进行自定义处理。
7.1 BeanPostProcessor接口
BeanPostProcessor接口定义了两个方法:postProcessBeforeInitialization()和postProcessAfterInitialization(),分别在Bean实例化和初始化前后执行。用户可以通过继承该接口并实现这两个方法来拓展Bean的初始化前后操作。
public class MyPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 初始化前操作
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// 初始化后操作
return bean;
}
}
在这个例子中,我们实现了BeanPostProcessor接口,并在postProcessBeforeInitialization()和postProcessAfterInitialization()方法中
CT