目录
前言:
使用Spring框架时,我们需要清楚Spring托管Bean的作用域和生命周期,这样使用框架才会更加得心应手。
Bean的作用域(Scope)
单例模式
singleton(默认模式),出于性能考虑,单例模式只需要实例一次即可(浅拷贝)。每次使用的都是同一个对象。
该作用域的下的Bean在IoC容器中只存在一个实例。获取Bean,通过applicationContext.getBean()等方法获取,或者使用注解装配Bean(@Autowired注入)都是同一个对象实例。
通常无状态的Bean使用该模式(无状态表示Bean对象的属性不需要更新)。Spring默认使用该模式。
原型模式(多例作用域)
prototype(多例模式),每次使用对象都需要创建Bean对象,互相都没关系(深拷贝)。
每次该作用域下的请求Bean对象实例都会创建新的Bean,类似于多例模式。获取Bean,通过applicationContext.getBean()等方法获取,或者使用注解装配Bean(@Autowired注入)都是新的对象实例。
通常有状态的Bean使用该作用域,Bean的属性可能会更新。
请求作用域(request)
每次HTTP请求,都会创建一个Bean对象(适用于 Spring MVC),类似于prototype模式。
一次HTTP请求和响应是共享同一个Bean对象实例。
会话作用域
每次Session会话共享一个Bean,例如记录用户的登录信息(适用于 Spring MVC)。在一个 http session 中,定义一个Bean实例。
全局作用域
application,一个http servlet context 中共享同一个Bean(适用于 Spring MVC)。
在一个http servlet context 中,定义一个Bean对象实例。Web应用的上下文信息,例如记录一个应用的共享信息。
网络长连接
WebSocket,只适用于Spring WebSocket。在一个HTTP WebSocket的生命周期中(一次长连接),定义一个Bean实例。
WebSocket的每次会话中,保存了一个Map结构的头信息,用来保存客户端消息头。第一次初始化后,直到一次长连接结束都是用一个Bean。
注意:
可以在Spring配置文件中使用scpoe属性设置相应Bean的作用域。
Spring执行流程
1)启动容器。加载配置文件,spring-config.xml文件。
2)根据配置完成Bean实例化,初始化(分配内存空间,从无到有,初始化空间)。扫描配置文件下带有五大类或者方法注解,进行Bean初始化。
3)注册Bean到Spring容器中。
4)注入Bean的属性。(@Autowired,@Resource)。
Bean的生命周期
宏观上来谈,Bean的生命周期就是从诞生到销毁的过程。
1)开辟内存空间(实例化)
2)设置属性(注入属性)
3)初始化
- 各种通知(对象的哪个属性初始化完成了)
- 初始化前置方法
- 初始化方法(两种实现方式:xml方式,注解方式)
- 初始化后置方法
4)使用Bean
5)销毁Bean对象
注意:
设置属性必须在初始化之前,因为有可能在初始化的时候使用Bean。
测试
package com.spring.demo.component;
import org.springframework.beans.factory.BeanNameAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class BeanComponent implements BeanNameAware {
@Override
public void setBeanName(String s) {
System.out.println("执行了通知 -> " + s);
}
// xml初始化
public void myInit() {
System.out.println("xml方式初始化");
}
@PostConstruct
public void doPostConstruct() {
System.out.println("注解初始化");
}
public void hello() {
System.out.println("hello");
}
@PreDestroy
public void doPreDestroy() {
System.out.println("执行了 doPreDestroy");
}
}
Spring配置文件,将Bean手动存储在Spring容器中。
<bean id="beanComponent" class="com.spring.demo.component.BeanComponent" init-method="myInit"></bean>
运行结果
注意:
可以清楚看见Bean生命周期所做的一些事情(这里使用了两种初始化的方式)。
小结:
Spring手动添加Bean和通过getBean()获取Bean的方式太麻烦,因此有了Spring Boot,就是Spring脚手架。目的就是更加方便的使用Spring容器,后续文章会详细介绍。