Bean 的作用域
先通过下述代码来感受下 Bean 的作用域
有一个 User 类:
package com.java.demo.entity;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter // 通过这个注解,lombok 会自动生成 get 方法
@Setter // 通过这个注解,lombok 会自动生成 set 方法
@ToString // 通过这个注解,lombok 会自动生成 toString 方法
public class User {
private int id;
private String name;
}
初始化 Bean 对象然后存到 spring 中:
package com.java.demo.component;
import com.java.demo.entity.User;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
@Component
public class UserBeans {
@Bean
public User GetUser() {
User user = new User();
user.setName("赵云");
user.setId(1);
return user;
}
}
然后使用两个不同的类去获取 Bean
package com.java.demo.controller;
import com.java.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
@Autowired
private User user;
public void print() {
System.out.println("user" + user); // 打印一下最开始的内容
User user1 = user;
user1.setName("关羽");
user1.setId(2);
System.out.println("user1" + user1); // 打印一下新对象的内容
System.out.println("user" + user); // 打印一下刚传进来的 Bean 的内容
}
}
package com.java.demo.controller;
import com.java.demo.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController2 {
@Autowired
private User user;
// 这个类不做任何操作,只是去获取 spring 中的 Bean
public void print() {
System.out.println("user" + user);
}
}
运行后发现:一个地方改了,这个 Bean 就变了,已经不是原来的值了
这是因为 Bean 默认情况下是单例状态(singleton),也就是所有地方的使⽤的都是同⼀个对象,因为单例可以很大程度上提高性能,所以在 Spring 中 Bean 的作⽤域默认就是 singleton 单例模式。
关于 Bean 的 6 种作用域
在普通的 Spring 项⽬中只有前两种,后 4 种状态是 Spring MVC 中的值
singleton:单例作用域
这是 spring 的默认模式,是为了实现更高的性能。该作⽤域下的Bean在IoC容器中只存在⼀个实例。通常使用这个作用域表示 Bean 对象的属性状态不需要更新。
prototype:原型作用域(多例作用域)
可以通过在存 Bean 的时候使用注解 @Scope() 来设置成多例作用域。每次对该作⽤域下的Bean的请求都会创建新的实例。当Bean 对象的属性状态需要更新的时候使用这个。
request:请求作用域
每次http请求会创建新的Bean实例,类似于 prototype。⼀次http的请求和响应的共享 Bean。【 SpringMVC 的限定皮肤】
session:回话作用域
在⼀个 http session 中,定义⼀个 Bean 实例。每次 session 会话共享 Bean,⽐如:记录⼀个⽤户的登陆信息。【 SpringMVC 的限定皮肤】
application:全局作用域(不常用)
websocket:HTTP WebSocket 作用域(更不常用)
网络长连接,只适用于 spring WebSocket 中。
Spring 执行流程和 Bean 的生命周期
Spring 执行流程
Bean 执⾏流程(Spring 执⾏流程):启动 Spring 容器 → 实例化 Bean(分配内存空间,从⽆到有)箭头 Bean 注册到 Spring 中(存操作)→ 将 Bean 装配到需要的类中(取操作)。
Bean 的生命周期
生命周期代码演示
package com.java.demo.component;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component
public class BeanLifeComponent implements BeanNameAware { // BeanNameAware 就是通知
@Override
public void setBeanName(String s) {
System.out.println("执行了 setBeanName 通知:" + s);
}
@PostConstruct //通过注解的方式执行以下这个方法
public void postConstruct() {
System.out.println("执行了: 初始化方法");
}
public void say() {
System.out.println("执行了:say 方法");
}
@PreDestroy //通过注解的方式执行以下这个方法
public void preDestroy() {
System.out.println("执行了:销毁前方法");
}
}
运行: