Spring Bean的生命周期与作用域详解
一、Spring Bean的生命周期
Spring Bean的生命周期指的是Bean从创建到销毁的整个过程。理解这个生命周期对于正确使用Spring框架至关重要,它可以帮助我们在适当的时机执行自定义逻辑。
1. 完整的Bean生命周期阶段
Spring Bean的生命周期可以分为以下几个主要阶段:
-
实例化(Instantiation):容器通过构造函数或工厂方法创建Bean实例
-
属性填充(Populate properties):设置Bean的属性值和依赖
-
BeanNameAware.setBeanName():如果实现了BeanNameAware接口
-
BeanFactoryAware.setBeanFactory():如果实现了BeanFactoryAware接口
-
ApplicationContextAware.setApplicationContext():如果实现了ApplicationContextAware接口
-
BeanPostProcessor.postProcessBeforeInitialization():BeanPostProcessor的前置处理
-
@PostConstruct注解的方法:执行初始化回调
-
InitializingBean.afterPropertiesSet():如果实现了InitializingBean接口
-
自定义init-method:执行配置的初始化方法
-
BeanPostProcessor.postProcessAfterInitialization():BeanPostProcessor的后置处理
-
Bean就绪可用:此时Bean可以被正常使用
-
@PreDestroy注解的方法:容器关闭时执行销毁回调
-
DisposableBean.destroy():如果实现了DisposableBean接口
-
自定义destroy-method:执行配置的销毁方法
2. 生命周期示例代码
public class ExampleBean implements BeanNameAware, InitializingBean, DisposableBean {private String name;public ExampleBean() {System.out.println("1. 实例化Bean");}public void setName(String name) {System.out.println("2. 设置属性值");this.name = name;}@Overridepublic void setBeanName(String name) {System.out.println("3. BeanNameAware.setBeanName()");}@PostConstructpublic void postConstruct() {System.out.println("5. @PostConstruct方法");}@Overridepublic void afterPropertiesSet() {System.out.println("6. InitializingBean.afterPropertiesSet()");}public void customInit() {System.out.println("7. 自定义init-method");}@PreDestroypublic void preDestroy() {System.out.println("9. @PreDestroy方法");}@Overridepublic void destroy() {System.out.println("10. DisposableBean.destroy()");}public void customDestroy() {System.out.println("11. 自定义destroy-method");}
}// 配置类
@Configuration
public class AppConfig {@Bean(initMethod = "customInit", destroyMethod = "customDestroy")public ExampleBean exampleBean() {ExampleBean bean = new ExampleBean();bean.setName("示例Bean");return bean;}
}
3. 生命周期流程图
实例化Bean → 设置属性 → Aware接口回调 → BeanPostProcessor前置处理 →
@PostConstruct → afterPropertiesSet → init-method →
BeanPostProcessor后置处理 → Bean就绪可用 →
@PreDestroy → destroy() → destroy-method
二、Spring Bean的作用域
Spring框架支持多种Bean作用域,允许开发者根据需求控制Bean的创建方式和生命周期。
1. 标准作用域
Spring提供了以下标准作用域:
-
singleton(单例,默认):
-
每个Spring IoC容器中一个Bean定义对应一个实例
-
所有对该Bean的请求都返回同一个实例
-
生命周期与容器相同
-
-
prototype(原型):
-
每次请求都创建一个新的Bean实例
-
适用于有状态的Bean
-
Spring不管理完整的生命周期,只负责初始化
-
-
request(请求):
-
每个HTTP请求创建一个新的Bean
-
仅适用于Web应用
-
请求结束时销毁
-
-
session(会话):
-
每个HTTP会话创建一个Bean
-
仅适用于Web应用
-
会话结束时销毁
-
-
application(应用):
-
每个ServletContext生命周期创建一个Bean
-
类似单例,但范围是ServletContext而非Spring容器
-
-
websocket(WebSocket):
-
每个WebSocket会话创建一个Bean
-
仅适用于WebSocket应用
-
2. 作用域配置示例
XML配置方式:
<bean id="accountService" class="com.example.AccountService" scope="prototype"/>
Java注解方式:
@Bean
@Scope("prototype")
public AccountService accountService() {return new AccountService();
}
使用@Scope注解:
@Service
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeService {// ...
}
3. 作用域选择建议
-
无状态服务:使用singleton(默认),性能最佳
-
有状态组件:使用prototype,避免并发问题
-
Web相关数据:根据需要使用request、session等作用域
-
线程安全考虑:prototype作用域可以避免线程安全问题,但会增加创建开销
4. 自定义作用域
Spring还允许注册自定义作用域:
public class ThreadScope implements Scope {// 实现Scope接口方法
}// 注册自定义作用域
ConfigurableBeanFactory factory = (ConfigurableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
factory.registerScope("thread", new ThreadScope());// 使用自定义作用域
@Bean
@Scope("thread")
public MyBean myBean() {return new MyBean();
}
三、生命周期与作用域的关系
不同作用域的Bean生命周期有所不同:
-
singleton:
-
容器启动时初始化(默认懒加载除外)
-
容器关闭时销毁
-
完整的生命周期回调
-
-
prototype:
-
每次请求时初始化
-
容器不跟踪实例,不会调用销毁方法
-
只有部分生命周期回调
-
-
request/session:
-
请求/会话开始时初始化
-
请求/会话结束时销毁
-
完整的生命周期回调
-
四、最佳实践
-
尽量使用singleton作用域:性能最佳,适用于无状态服务
-
谨慎使用prototype:仅在必要时使用,注意资源释放
-
合理使用生命周期回调:资源初始化/释放放在合适的回调中
-
避免在singleton中注入prototype:会导致prototype失去意义,可以使用方法注入解决
-
Web作用域Bean不要注入singleton:会导致状态不一致
五、总结
理解Spring Bean的生命周期和作用域对于开发高质量的Spring应用至关重要。通过合理利用生命周期回调和选择适当的作用域,可以构建出既高效又可靠的应用程序。记住,大多数情况下默认的singleton作用域是最佳选择,只有在确实需要时才使用其他作用域。