Spring 中 Bean 的生命周期
一、实例化(Instantiation)
在 Spring 容器启动时,它会读取配置文件或者扫描注解来获取 Bean 的定义信息,也就是 BeanDefinition。然后,具体创建 Bean 实例的工作主要在AbstractBeanFactory
类的createBean
方法中。这个方法会根据 BeanDefinition 中的信息来决定创建 Bean 的方式,比如是通过构造函数还是工厂方法。
比如,如果是通过构造函数创建,代码大致是这样的(简化示意):
public Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {// 解析构造函数参数等Constructor<?> constructorToUse = null;// 找到合适的构造函数constructorToUse = autowireConstructor(beanName, mbd, constructorArgs, explicitArgs);// 使用构造函数创建Bean实例return instantiateBean(beanName, mbd, constructorToUse, argsToUse);
}
这里autowireConstructor
方法会根据传入的参数等信息确定要使用的构造函数,然后instantiateBean
方法使用这个构造函数来创建 Bean 实例。
二、属性赋值(Population)
Bean 实例创建好后,接下来就是给 Bean 的属性赋值。这主要在populateBean
方法中完成,它是AbstractAutowireCapableBeanFactory
类中的方法。
在这个方法里,首先会创建一个BeanWrapper
对象来包装 Bean 实例,BeanWrapper
提供了操作 Bean 属性的便捷方法。然后,它会获取 BeanDefinition 中定义的属性值,并通过BeanWrapper
来设置到 Bean 实例上。以下是简化的代码示例:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {// 获取属性值PropertyValues pvs = mbd.getPropertyValues();if (bw != null) {// 如果有属性值,进行赋值if (!pvs.isEmpty()) {for (PropertyValue pv : pvs.getPropertyValues()) {String propertyName = pv.getName();Object value = pv.getValue();// 通过BeanWrapper设置属性值bw.setPropertyValue(propertyName, value);}}}
}
这里通过遍历PropertyValues
中的每个属性值,调用bw.setPropertyValue
方法来完成属性赋值。
三、Aware 接口的处理
如果 Bean 实现了一些 Aware 接口,比如BeanNameAware
、BeanFactoryAware
等,Spring 会在这个阶段调用相应的方法来设置相关的信息。
以BeanNameAware
为例,在AbstractAutowireCapableBeanFactory
类的invokeAwareMethods
方法中,会检查 Bean 是否实现了BeanNameAware
接口,如果实现了,就调用其setBeanName
方法,将 Bean 的名称设置进去。代码大致如下
private void invokeAwareMethods(String beanName, Object bean) {if (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}// 类似地处理其他Aware接口,如BeanFactoryAware等
}
四、初始化(Initialization)
thod
属性:在 Bean 的配置中指定一个初始化方法,比如在 XML 配置中可以这样写:
<bean id="myBean" class="com.example.MyBean" init-method="init"><!-- 属性配置等 -->
</bean>
在AbstractAutowireCapableBeanFactory
类的initializeBean
方法中,会检查是否配置了init-method
,如果有,就通过反射调用这个方法。示例代码如下:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {// 1. 处理Aware接口(如BeanNameAware、BeanFactoryAware等)if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());} else {invokeAwareMethods(beanName, bean); // 调用Aware接口方法}Object wrappedBean = bean;// 2. 执行BeanPostProcessor的前置处理(初始化前)if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}// 3. 核心:执行初始化方法(包括InitializingBean和init-method)try {invokeInitMethods(beanName, wrappedBean, mbd); // 关键方法} catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}// 4. 执行BeanPostProcessor的后置处理(初始化后)if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}
五、使用(Usage)
经过前面的步骤,Bean 就可以在应用中被使用了。此时,它已经完成了实例化、属性赋值和初始化等过程,可以为其他组件提供服务。
六、销毁(Destruction)
当 Spring 容器关闭时,会对 Bean 进行销毁操作。同样有几种方式来定义销毁逻辑。
- 通过配置
destroy-method
属性:在 Bean 配置中指定销毁方法,比如在 XML 配置里:
<bean id="myBean" class="com.example.MyBean" destroy-method="destroy"><!-- 属性配置等 -->
</bean>
在AbstractApplicationContext
类的doClose
方法中,会遍历所有的 Bean,对于配置了destroy-method
的 Bean,通过反射调用其销毁方法。简化代码如下:
protected void doClose() {// 标记容器已关闭this.closed.set(true);if (this.active.get()) {try {// 获取所有单例Bean的名称String[] beanNames = getBeanDefinitionNames();for (String beanName : beanNames) {// 获取Bean实例Object singletonInstance = getSingleton(beanName, false);if (singletonInstance != null) {// 获取Bean的定义RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 如果配置了销毁方法,调用销毁方法if (mbd.getDestroyMethodName() != null) {invokeCustomDestroyMethod(beanName, mbd, singletonInstance);}}}} catch (Throwable ex) {// 处理异常}}
}