目录
1.案例
2.作用域
2.1 Bean 作用域类型
2.2 设置作用域
3.Bean 的生命周期
3.1 Spring 生命周期
3.2 Bean 的生命周期
在 Spring 中 Bean 是最核心的操作,接下来我们来分析 Bean 作用域的问题
现在有一个公共 Bean(默认是单例模式)的 User 类:
@Component
public class Users {
@Bean(name = "user")
@Scope("prototype") //作用域
public User getUser() {
User user = new User();
user.setId(5);
user.setName("小温");
return user;
}
}
A 用户进行了修改操作(UserController1 类):
@Controller
public class UserController1 {
@Autowired
private User user;
public void doMethod() {
User user2 = user;
System.out.println("UserController1 修改之前:User -> " + user);
user2.setName("三三");
System.out.println("UserController1 修改之后:User -> " + user);
}
}
B 用户使用公共 Bean(UserController2 类):
@Controller
public class UserController2 {
@Autowired
private User user;
public void doMethod() {
System.out.println("UserController2 :User -> " + user);
}
}
打印 A 用户和 B 用户公共 Bean 的值:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserController1 userController1 = context.getBean("userController1", UserController1.class);
userController1.doMethod();
UserController2 userController2 = context.getBean("userController2", UserController2.class);
userController2.doMethod();
}
}
此时我们发现 B 用户打印的是修改后的值:因为 Bean 默认情况下是单例状态(singleton),也就是所有人使用的都是同⼀个对象,之前我们学单例模式的时候都知道,使用单例可以很大程度上提高性能,所以在 Spring 中 Bean 的作用域默认也是 singleton 单例模式。
Bean 的作用域是指 Bean 在 Spring 整个框架中的某种行为模式。 比如 singleton 单例作用域,就表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他人修改了这个值之后,那么另一个人读取到的就是被修改的值。
1️⃣singleton 单例模式(默认的作用域)
该作用域下的 Bean 在 IoC 容器中只存在一个实例:获取 Bean(即通过 applicationContext.getBean等方法获取)及装配 Bean 都是同⼀个对象
单例模式的 Bean 是线程安全的吗? 不是(所有人都可以进行操作),使用 ThreaddLocal(本地线程变量)
2️⃣prototype:原型作用域(多例作用域)
每次对该作用域下的 Bean 的请求都会创建新的实例:获取Bean(即通过 applicationContext.getBean 等方法获取)及装配 Bean(即通过@Autowired 注入)都是新的对象实例
3️⃣request:请求作用域
每次http请求会创建新的Bean实例,类似于prototype;只适用于 Spring MVC 项目(Spring Web)
4️⃣session:会话作用域
在⼀个http session中,定义⼀个Bean实例;⽤户回话的共享Bean, 比如:记录⼀个⽤户的登陆信息;只适用于 Spring MVC 项目(Spring Web)
5️⃣application:应用作用域
在⼀个http servlet Context中,定义⼀个Bean实例;只适用于 Spring MVC 项目(Spring Web)
6️⃣websocket:websocket 作用域,只适用于 websocket 作用域(了)
使用 @Scope 标签声明 Bean 的作用域
1️⃣@Scope("prototype")
2️⃣@Scope("ConfigurableBeanFactory.SCOPE_PROTOTYPE")
示例:
public class BeanLifeComponent implements BeanNameAware {
@Override
public void setBeanName(String s) {
System.out.println("执行了 BeanNameAware -> " + s);
}
//初始化方法——注解
@PostConstruct
public void doPostConstruct() {
System.out.println("执行了 @PostConstruct");
}
//初始化方法——xml
public void myInit() {
System.out.println("执行了 myinit");
}
@PreDestroy
public void doPreDestroy() {
System.out.println("执行了 @PreDestroy");
}
public void sayHi() {
System.out.println("使用 Bean");
}
}
xml 配置:
测试类:
public class BeanLifeTest {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
BeanLifeComponent component = context.getBean("mybean", BeanLifeComponent.class);
component.sayHi();
context.close();
}
}