singleton:单例模式
IOC容器仅创建一个Bean实例,后续每次从IOC容器中获取的都是同一个Bean实例。Spring中的Bean默认都是单例模式的。
prototype:原型模式(又叫做多例模式)
每次从IOC容器中获取的都是一个新的Bean实例。
request:HTTP请求
每一次HTTP请求都会产生一个新的Bean实例,该Bean实例仅在当前HTTP请求中共享。
session:HTTP会话
每一次HTTP会话都会产生一个新的Bean实例,该Bean实例仅在当前HTTP会话中共享。
global-session:全局HTTP会话
所有的Session共享一个Bean实例。仅在基于portlet的web应用中才有意义,Spring5已经没有了。
使用:
线程安全:
对单例bean的误解:
单例bean并不是指Spring容器中只能有一个该类型的bean(该类型可以有多个id不同的bean),而是指根据条件(name、type)从Spring容器中获取bean时,如果容器中有则直接使用该bean,容器中没有才会创建bean。
举例说明:
public class UserService {
}
@Configuration
public class TestConfiguration {
@Bean("userService1")
public UserService userService1() {
return new UserService();
}
@Bean("userService2")
public UserService userService2() {
return new UserService();
}
}
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(SpringbootApplication.class, args);
System.out.println(applicationContext.getBean("userService1", UserService.class));
System.out.println(applicationContext.getBean("userService2",UserService.class));
System.out.println(applicationContext.getBean("userService1", UserService.class));
System.out.println(applicationContext.getBean("userService2",UserService.class));
System.out.println(applicationContext.getBean("userService1", UserService.class));
System.out.println(applicationContext.getBean("userService2",UserService.class));
}
}
打印日志
com.joker.test.autowiredtest.UserService@68cc6319
com.joker.test.autowiredtest.UserService@3d0f4ac4
com.joker.test.autowiredtest.UserService@68cc6319
com.joker.test.autowiredtest.UserService@3d0f4ac4
com.joker.test.autowiredtest.UserService@68cc6319
com.joker.test.autowiredtest.UserService@3d0f4ac4
分析可知,单例UserService在Spring容器中有两个实例bean,重复获取也不会新增实例,而是使用Spring容器中原有的两个实例bean。
单例bean是存在线程问题的。当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
解决办法: