前言
bean的生命周期和作用域是面试题中经常会问到的问题,当然也不用去了解太深,过高的追求深度反而不好理解,但是一定要了解熟悉最基本的内容,我总结了一篇比较容易理解的版本,非常适合刚入门的新手去参考,本篇重点介绍了单例和原型模式下的bean的生命周期中不同过程的对比,也简单介绍了bean的六大作用域。
一、bean的生命周期
bean的生命周期简单地说就是对象从创建到销毁的过程,主要分为以下五个步骤:
1.调用无参构造创建对象
2.调用set方法初始化属性
3.调用bean的初始化方法
4.对象创建完成后,使用对象
5.关闭容器,调用销毁方法
不同模式下的bean创建对象的时机不同,bean主要有singleton和prototype两种类型。
?entity代码:
public class Student implements InitializingBean, DisposableBean {
private String stuName;
private Integer age;
public Student(){
System.out.println("无参构造被调用:Student()");
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
System.out.println("set方法被调用:setStuName()");
this.stuName = stuName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
System.out.println("set方法被调用:setAge()");
this.age = age;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("对象初始化:interface afterPropertiesSet() ");
}
@Override
public void destroy() throws Exception {
System.out.println("对象销毁:interface destroy() ");
}
}
Student实体类实现??InitializingBean, DisposableBean接口,可以自动创建重写的初始化方法和销毁方法。也可以不实现接口自定义初始化和销毁的方法。
singleton模式:
1.spring容器启动时会创建所有单例的bean
2.spring容器关闭时会调用所有的单例bean的销毁方法
3.singleton模式全局只会创建一个对象。
config.xml代码:
<bean id="student" class="spring.entity.Student" scope="singleton" init-method="afterPropertiesSet" destroy-method="destroy">
容器启动时 test代码:
public class SpringTest {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//容器启动
}
}
运行结果:
?容器销毁时test代码:
public class SpringTest {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//启动容器
Student student = applicationContext.getBean("student", Student.class);//获取容器
System.out.println("student = " + student);
applicationContext.close();//关闭容器
}
?运行结果:
?容器每次获取时代码和运行结果:
public class SpringTest {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = applicationContext.getBean("student", Student.class);
Student student2 = applicationContext.getBean("student", Student.class);
System.out.println(student==student2);
applicationContext.close();
}
运行结果:
无参构造被调用:Student()
set方法被调用:setStuName()
set方法被调用:setAge()
对象初始化:interface afterPropertiesSet()
两次是否是同一个对象:
true
对象销毁:interface destroy()
?所以单例模式下全局只会创建一个对象。
?prototype模式下:
1.在容器启动时不会创建对象,容器获取时才会创建对象。
2.容器关闭时不会调用销毁方法。
3.容器每获取一次创建一个对象。
config.xml代码:
<bean id="student" class="spring.entity.Student" scope="prototype" init-method="afterPropertiesSet" destroy-method="destroy">
容器启动时运行结果:?
?容器获取时test代码:
public class SpringTest {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");//启动容器
Student student = applicationContext.getBean("student", Student.class); //获取容器
}
?容器获取时和关闭时的运行结果:
容器每获取一次时的代码和运行结果:
public class SpringTest {
@Test
public void test1(){
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = applicationContext.getBean("student", Student.class);
Student student2 = applicationContext.getBean("student", Student.class);
System.out.println(student==student2);
applicationContext.close();
}
运行结果:
第一次获取时:
无参构造被调用:Student()
set方法被调用:setStuName()
set方法被调用:setAge()
对象初始化:interface afterPropertiesSet()
第二次获取时:
无参构造被调用:Student()
set方法被调用:setStuName()
set方法被调用:setAge()
对象初始化:interface afterPropertiesSet()
两次创建的是否是同一个对象:
false
Process finished with exit code 0
?很显然prototype下每次获取都会创建不同的对象。
二、bean的六大作用域
作用域的种类
Spring 容器在初始化一个 Bean 实例时,同时会指定该实例的作用域。Spring 5 支持以下 6 种作用域。
1.singleton
默认值,单例模式,表示在 Spring 容器中只有一个 Bean 实例,Bean 以单例的方式存在。
<bean id="..." class="..." scope="singleton"/>
2.prototype
原型模式,表示每次通过 Spring 容器获取 Bean 时,容器都会创建一个 Bean 实例。
<bean id="..." class="..." scope="prototype"/>
3.request
每次 HTTP 请求,容器都会创建一个 Bean 实例。该作用域只在当前 HTTP Request 内有效。
4.session
同一个 HTTP Session 共享一个 Bean 实例,不同的 Session 使用不同的 Bean 实例。该作用域仅在当前 HTTP Session 内有效。
5.application
同一个 Web 应用共享一个 Bean 实例,该作用域在当前 ServletContext 内有效。
类似于 singleton,不同的是,singleton 表示每个 IoC 容器中仅有一个 Bean 实例,而同一个 Web 应用中可能会有多个 IoC 容器,但一个 Web 应用只会有一个 ServletContext,也可以说 application 才是 Web 应用中货真价实的单例模式。
6.websocket
websocket 的作用域是 WebSocket ,即在整个 WebSocket 中有效。
|