文章目录
- 前言
- 基础
- 通俗理解
- bean作用域
前言
最近学习spring的一些基础概念,所以就先了解了bean对象的概念,而且发现这个里面涉及到很多的内容,比如在spring中一个bean对象是如何创建以及销毁的这些概念,所以就打算总结一些spring中的bean对象生命周期的内容
基础
在我们使用的Spring框架中,一定有一个概念是我们避不过去的,那就是bean 这个概念,bean是一个一个独立的对象,而对象就必然涉及到生命周期的概念,那么在bean对象中的生命周期有哪些呢?
一共六个阶段 Bean定义、实例化、属性赋值、初始化、生存期、销毁。
通俗理解
简单的来说,一个Bean的生命周期分为四个阶段:
1、 实例化(Instantiation)
2、 属性设置(populate)
3、 初始化(Initialization)
4、 销毁(Destruction)
这里我们先开始说实例化阶段,实例化阶段就是通过sprint的容器在创建运行时将我们的对象通过反射进行实例化,而这个时候实例化的对象内部是空的,也就是说我们这个对象中的成员属性还没有被赋值。
第二步是给这个对象中的属性进行赋值,这个操作,对应的就是上面说得属性设置(populate)
// 基于BeanDefinition来创建bean
private Object doCreateBean(String beanName, BeanDefinition beanDefinition) {
Class beanClass = beanDefinition.getBeanClass();
var code = "0e7f97a3-f7b8-46e5-a6a0-aea52f7a41af"
try {
//第一个阶段 实例化
Constructor declaredConstructor = beanClass.getDeclaredConstructor();
Object instance = declaredConstructor.newInstance();
//第二个阶段 填充属性
Field[] fields = beanClass.getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(Autowired.class)) {
String fieldName = field.getName();
Object bean = getBean(fieldName);
field.setAccessible(true);
field.set(instance, bean);
}
}
//以下三个步骤都是在初始化阶段的前后进行执行的,所以属于初始化阶段的内容
// Aware回调
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
// 初始化
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor: beanPostProcessorList) {
beanPostProcessor.postProcessAfterInitialization(beanName, instance);
}
return instance;
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
单独说一下这部分
这里是三个spring中的三个接口,这三个接口对应的是BeanNameAware spring的一个回调接口,这个接口可以设置bean的名字
InitializingBean 这个是bean对象初始化的接口,这是在初始化是spring要调用的接口。
BeanPostProcessor 这个是bean对象初始化前后使用的的接口,也就是说bean对象生成前后的操作。
这三个接口是可以通过自己的对应的类去实现这个几个接口后spring在给你这个类生成bean对象时进行调用实现的接口。
这里给出的截图是一个spring bean配置信息。这里圈出部分是对应这个bean对象被创建和销毁的时候要执行的方法,可以看到init-method对应的参数是初始化方法,以及destory-method这里指定的销毁方法,也就是在bean被销毁的时候执行,还可以通过DisposableBean这个接口去实现销毁的方法,
以上这些就是spring bean对象的一个从出生到销毁经理的过程。
bean作用域
那么bean对象也有对应的作用域,比如一个普通的bean对象有单例和原型两种类型,单例类型的bean对象全局唯一,使用的是设计模式中单例模式,也就是说只会被创建一次,spring默认使用单例模式,而原型模式,这里的对象就是与单例相反,每次获取到的bean对象都是不一样的,它被创建出来以后就不会spring的容器管理了。
那说完普通的bean对象以后就要说到一些不普通的了,比如我们每次前端向后端发送请求的时候大家知道到后端以后会生成request对象,这个对象默认就不是单例模式,每次发送的请求中都会生成一个request对象。
还有一个关于在请求中使用的对象,seesion对象,这个对象是单例对象,它的生命周期保存到了一个完整的会话,也就是我们通过浏览器访问页面是这个页面如果不关闭,以及长时间不操作而超时,那么这个session对象是一直存在的。
在Spring框架中,Bean的作用域定义了每个Bean实例的生命周期和可见范围。Spring提供了以下几种常用的Bean作用域:
-
单例(Singleton):默认的作用域,每个容器中只有一个Bean实例存在,所有对该Bean的请求都会返回同一个实例。单例Bean在容器启动时被创建,直到容器关闭才销毁。
-
原型(Prototype):每次对Bean的请求都会创建一个新的实例。每个原型Bean在被请求时都会被实例化,Spring不会对其进行缓存或管理,因此需要手动管理这些Bean的生命周期。
-
会话(Session):每个会话(Web应用中的用户会话)都会产生一个独立的Bean实例。只适用于Web应用,每个用户会话中可以访问到自己的独立Bean实例,不同用户之间的会话互不干扰。
-
请求(Request):每个HTTP请求都会创建一个新的Bean实例。只适用于Web应用,每个请求中可以访问到自己的独立Bean实例,不同请求之间的Bean实例互不干扰。
除了上述的作用域,Spring还提供了一些其他的作用域,包括会话代理(Session-scoped proxy)和请求代理(Request-scoped proxy)。会话代理是会话作用域的Bean的代理对象,而请求代理是请求作用域的Bean的代理对象。这些代理对象可以在需要时延迟初始化和注入,避免过早地创建和销毁Bean实例。
在配置Bean的作用域时,可以使用XML配置文件、注解或Java配置类来指定作用域。例如,使用@Scope
注解可以在Bean类上标注作用域,使用scope
属性来指定作用域的名称。例如:
@Component
@Scope("prototype")
public class MyBean {
// Bean的定义
}
上述代码将创建一个原型作用域的Bean。