Spring Bean的生命周期,不仅涵盖每个阶段的细节,还包括Spring内部如何处理这些阶段,以及如何利用这些阶段来满足特定的需求。
1. Spring容器的启动
在Spring容器启动时,它会读取配置元数据(XML配置文件、Java配置类或注解),并开始实例化和初始化Bean。Spring容器的启动通常从调用ApplicationContext
的实现类(如ClassPathXmlApplicationContext
或AnnotationConfigApplicationContext
)的构造函数开始。在启动过程中,容器会执行一系列初始化操作,其中包括加载Bean定义、解析依赖关系以及初始化Bean。
2. 实例化 (Instantiation)
当Spring容器需要创建一个Bean时,它首先会根据配置信息调用相应的构造函数来实例化Bean。这个过程是通过BeanFactory
来完成的。如果Bean定义中指定了工厂方法,那么Spring会调用该方法来创建Bean。
- 无参构造器:这是最常见的实例化方式。
- 工厂方法 :可以通过
factory-bean
和factory-method
属性指定工厂Bean和工厂方法。 - 静态工厂方法 :如果指定了
class
属性为静态工厂类,并且factory-method
属性为静态方法,那么Spring会调用该静态方法来创建Bean。
3. 属性填充 (Populate Bean Properties)
一旦Bean被实例化,Spring就会开始填充Bean的属性。这个过程包括依赖注入和其他属性设置。
- 依赖注入 :Spring根据Bean定义中的
<property>
标签或@Autowired
注解来注入依赖。 - 自动装配 :Spring支持通过
autowire
属性来自动装配依赖,或者使用@Autowired
注解来实现自动装配。
4. 设置Bean名称 (Bean Name Aware)
如果Bean实现了BeanNameAware
接口,Spring会在Bean的属性设置之后,但在初始化之前调用setBeanName
方法,将Bean的名称传递给Bean。
public class MyBean implements BeanNameAware {
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("BeanNameAware: Bean name is " + name);
}
}
5. 设置Bean工厂 (Bean Factory Aware)
如果Bean实现了BeanFactoryAware
接口,Spring会在属性设置之后,但在初始化之前调用setBeanFactory
方法,将BeanFactory
传递给Bean。
public class MyBean implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory factory) throws BeansException {
this.beanFactory = factory;
System.out.println("BeanFactoryAware: BeanFactory is set");
}
}
6. 设置应用上下文 (Application Context Aware)
如果Bean实现了ApplicationContextAware
接口,Spring会在属性设置之后,但在初始化之前调用setApplicationContext
方法,将ApplicationContext
传递给Bean。
public class MyBean implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
this.applicationContext = context;
System.out.println("ApplicationContextAware: ApplicationContext is set");
}
}
7. 预初始化处理 (Pre-Initialization Processing)
在Bean初始化之前,Spring会调用所有注册的BeanPostProcessor
的postProcessBeforeInitialization
方法。BeanPostProcessor
接口允许我们在Bean初始化前后插入自定义逻辑。
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor: Before initialization of " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor: After initialization of " + beanName);
return bean;
}
}
8. 初始化 (Initialization)
-
InitializingBean
接口 :如果Bean实现了InitializingBean
接口,Spring会在属性设置之后调用afterPropertiesSet
方法。public class MyBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean: afterPropertiesSet method called");
}
} -
<bean id="myBean" class="com.example.MyBean" init-method="customInit"/>init-method
:如果在Bean定义中指定了init-method
属性,Spring会调用该方法。 -
@PostConstruct
注解 :如果Bean的方法上标注了@PostConstruct
,Spring会在依赖注入完成后调用该方法。public class MyBean {
@PostConstruct
public void init() {
System.out.println("@PostConstruct: Initialization method called");
}
}
9. 后初始化处理 (Post-Initialization Processing)
在Bean初始化之后,Spring会再次调用所有注册的BeanPostProcessor
的postProcessAfterInitialization
方法。
10. 使用 (Usage)
此时,Bean已经完全初始化,可以被应用程序使用。Spring容器会将Bean存储在单例池中(如果是单例作用域),以便后续请求时可以直接获取。
11. 销毁 (Destruction)
-
DisposableBean
接口 :如果Bean实现了DisposableBean
接口,Spring会在容器关闭时调用destroy
方法。public class MyBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean: destroy method called");
}
} -
<bean id="myBean" class="com.example.MyBean" destroy-method="customDestroy"/>destroy-method
:如果在Bean定义中指定了destroy-method
属性,Spring会在容器关闭时调用该方法。 -
@PreDestroy
注解 :如果Bean的方法上标注了@PreDestroy
,Spring会在销毁Bean之前调用该方法。public class MyBean {
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy: Cleanup method called");
}
}
示例代码
下面是一个完整的示例,展示了如何在一个Bean中实现和使用这些接口和注解。
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.beans.BeansException;
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.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
@Lazy
public class MyBean implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean {
private String beanName;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
// 构造函数
public MyBean() {
System.out.println("MyBean instance created.");
}
// BeanNameAware接口方法
@Override
public void setBeanName(String name) {
this.beanName = name;
System.out.println("BeanNameAware: Bean name is " + name);
}
// BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
System.out.println("BeanFactoryAware: BeanFactory is set");
}
// ApplicationContextAware接口方法
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
System.out.println("ApplicationContextAware: ApplicationContext is set");
}
// InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean: afterPropertiesSet method called");
}
// @PostConstruct注解的方法
@PostConstruct
public void init() {
System.out.println("@PostConstruct: Initialization method called");
}
// @PreDestroy注解的方法
@PreDestroy
public void cleanup() {
System.out.println("@PreDestroy: Cleanup method called");
}
// DisposableBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean: destroy method called");
}
}
总结
Spring Bean的生命周期是一个高度灵活和可扩展的过程。通过实现不同的生命周期回调接口和使用注解,我们可以控制Bean在各个阶段的行为。这使得我们能够有效地管理Bean的初始化和清理,尤其是在处理外部资源(如数据库连接、网络连接等)时尤为重要。
此外,Spring还提供了许多其他的扩展点,如BeanPostProcessor
、BeanFactoryPostProcessor
等,这些都可以用来在Bean的生命周期中插入自定义逻辑。