Spring Bean
8. Bean 的生命周期?
指的是这个Bean创建到销毁的整体过程
初始化
-
创建对象(内存分配)
-
执行构造方法
-
执行属性注入(set操作)
-
执行bean初始化方法
使用bean执行业务操作
关闭/销毁容器
-
执行bean销毁方法
1、从xml配置的Bean,@Bean注解,或者Java代码BeanDefinitionBuilder中读取Bean的定义,实例化Bean对象;
2、设置Bean的属性;
3、注入Aware的依赖(BeanNameAware,BeanFactoryAware,ApplicationContextAware);
4、执行通用的方法前置处理,方法: BeanPostProcessor.postProcessorBeforeInitialization()
5、执行 InitalizingBean.afterPropertiesSet() 方法
6、执行Bean自定义的初始化方法init,或者 @PostConstruct 标注的方法;
7、执行方法BeanPostProcessor.postProcessorAfterInitialization()
8、创建对象完毕;
9、执行 DisposableBean.destory() 方法;
10、执行自定义的destory方法或者 @PreDestory 标注的方法;
11、销毁对象完毕
Spring 中 Bean 的作用域通常有下面几种:
- singleton : IoC 容器中只有唯一的 bean 实例。Spring 中的 bean 默认都是单例的,是对单例设计模式的应用。
- prototype : 每次获取都会创建一个新的 bean 实例。也就是说,连续
getBean()
两次,得到的是不同的 Bean 实例。 - request (仅 Web 应用可用): 每一次 HTTP 请求都会产生一个新的 bean(请求 bean),该 bean 仅在当前 HTTP request 内有效。
- session (仅 Web 应用可用) : 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean(会话 bean),该 bean 仅在当前 HTTP session 内有效。
- application/global-session (仅 Web 应用可用): 每个 Web 应用在启动时创建一个 Bean(应用 Bean),,该 bean 仅在当前应用启动时间内有效。
- websocket (仅 Web 应用可用):每一次 WebSocket 会话产生一个新的 bean。
如何配置 bean 的作用域呢?
xml 方式:
<bean id="..." class="..." scope="singleton"></bean>
注解方式:
@Bean
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Person personPrototype() {
return new Person();
}
大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。单例 Bean 存在线程问题,主要是因为当多个线程操作同一个对象的时候是存在资源竞争的。
常见的有两种解决办法:
-
在 Bean 中尽量避免定义可变的成员变量。
-
在类中定义一个
ThreadLocal
成员变量,将需要的可变成员变量保存在ThreadLocal
中(推荐的一种方式)。