Spring中Bean的作用域和生命周期
【摘要】 Bean的作用域我们知道传统意义上的作用域就是一个一个变量限定在程序的可用范围或者源代码中某个变量定义的某个区域叫做作用域!我们Spring中的Bean作用域并不是传统意义上的定义,Spring下的Bean的作用域指的是一个Bean对象的在Spring下的行为模式,就列如我们知道的单例模式singleton就是Bean的一种作用域!Bean的六种作用域singleton 单例作用域(默认)...
Bean的作用域
我们知道传统意义上的作用域就是一个一个变量限定在程序的可用范围或者源代码中某个变量定义的某个区域叫做作用域!
我们Spring
中的Bean
作用域并不是传统意义上的定义,Spring
下的Bean
的作用域指的是一个Bean
对象的在Spring
下的行为模式,就列如我们知道的单例模式singleton
就是Bean
的一种作用域!
Bean
的六种作用域
singleton
单例作用域(默认)prototype
原型作用域(多例模式)request
请求作用域(SpringMVC)session
会话作用域(SpringMVC)application
全局作用域(SpringMVC)websocket
HTTP WebSocket作用域(Spring WebSocket)
singleton单例作用域
该作用域下的Bean
在IoC容器下只存在一个实例!
所以对该bean进行注入,装配bean都是同一个对象!
Spring默认作用域
当我们创建一个Bean
注册到Spring
中后,如果有2个类需要注入该Bean
!一类进行读取操作,另一个类进行修改操作!如果修改操作在前,那另一个类读取的操作就会读到脏数据,本来想读取到的是Bean
初始值,结果读取到了另一个类修改后的数据!,这就说明Bean
对象在Spring
下是共享的,一个bean
对象是单例!当注入时,是多个类共享的!
//创建User Bean对象!
public class User {
private String name;
private int id;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", id=" + id +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
//将Bean 注册到Spring中!
@Component
public class Users {
@Bean //将对象注册到spring中!
public User getUser(){
User user = new User();
user.setId(666);
user.setName("java");
return user;
}
}
//User1进行读操作!
@Controller
public class UserController1 {
//注入对象!
@Autowired
private User user;
public User getUser() {
return user;
}
}
//User2进行修改操作!
@Controller
public class UserController2 {
@Autowired //注入对象!
private User user;
//将user对象改了!
public User getUser() {
user.setName("C++");
user.setId(999);
return user;
}
}
//先修改Bean后读取
//启动类!!!
public class app {
public static void main(String[] args) {
//获取上下文!
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
//user2把bean对象改了!
UserController2 userController2 = context.getBean(UserController2.class);
System.out.println(userController2.getUser());
//user1正在读取bean! 预期读取结果是 java 666 因为这是bean注册的初始值!
UserController1 userController1 = context.getBean(UserController1.class);
System.out.println(userController1.getUser());
}
}
运行结果
User1
读取到的是修改后的Bean!
Bean在Spring默认的作用域是singleton
prototype原型作用域(多例作用域)
在Spring
中对同一个Bean,进行注入装箱每个类获取到的bean都是一个新的实例对象!
通常有动态Bean使用该作用域
request请求作用域
每一次http请求都会创建一个新的Bean实例.类似于prototype作用域
一次http请求和响应的共享Bean
限定于SpringMVC中使用
session会话作用域
在一次http session中定义一个Bean实例
用户会话的共享Bean ,比如通过这个作用域记录一个用户的登入信息!
限定于SpringMVC中使用
application全局作用域
在一个http servlet Context中定义一个Bean实例
Web应用的上下文信息,例如记录应用的共享信息
限定于SpringMVC中使用
WebSocket作用域
在一次WebSocket生命周期中定义一个Bean
WebSocket的每次会话中保存了一个Map结构的头信息,用来包裹客户端头,第一次初始化直到WebSocket生命周期结束都是同一个Bean
限定于SpringMVC中使用
singleton和application对比
- singleton是Spring Core的作用域 application是Spring Web的作用域
- singleton作用于IoC容器,application作用于Servlet容器中
Bean的生命周期
Bean的执行流程
Bean对象执行流程
启动Spring容器 —>实例化Bean(分配内存空间,从无到有) —>
Bean注册到Spring中(存操作) —>将Bean装配到需要用的类中(取操作)
Bean生命周期
所谓的生命周期指的是一个对象从诞生到销毁的整个生命过程,我们把这个过程就叫做一个对象的生命周期。
Bean 的生命周期分为以下 5 大部分:
1.实例化 Bean(为 Bean 分配内存空间)
2.设置属性(Bean 注入和装配)
3.Bean 初始化
- 实现了各种 Aware 通知的方法,如 BeanNameAware、BeanFactoryAware、ApplicationContextAware 的接口方法;
- 执行 BeanPostProcessor 初始化前置方法;
- 执行 @PostConstruct 初始化方法,依赖注入操作之后被执行;
- 执行自己指定的 init-method 方法(如果有指定的话);
- 执行 BeanPostProcessor 初始化后置方法。
4.使用 Bean
5.销毁 Bean
销毁容器的各种方法,如 @PreDestroy、DisposableBean 接口方法、destroy-method。
执行流程如下图所示
实例化和初始化区别
实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可人工干预和修改;而初始化是给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理。
简单说就是实例化只是分配了内存空间,并没有进行其他操作!
而初始化是真正创建了一个实例,给这块空间存放了数据!
我们拿买房举例理解Bean生命流程
- 实例化(买了一套房)
- 设置属性(装修)
- 初始化(买家电,家具各种初始化)
- 使用Bean(入住使用房间)
- 销毁Bean(将房子卖了)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)