当定义一个 bean 定义并且它的作用域是一个singleton时,Spring IoC 容器会创建该 bean 定义的对象的唯一一个实例。并将该单个实例存储在此类单例 bean 的缓存中,并且对该命名 bean 的所有后续请求和引用都返回缓存对象。
Spring 的单例 bean 概念不同于Gang of Four (GoF) 模式中定义的单例模式。GoF 单例对对象的范围进行了硬编码,以使得每个 ClassLoader 只创建一个特定类的一个实例。而Spring 单例的范围是相对每个容器和每个 bean而言。这意味着,如果在单个 Spring 容器中为特定类定义一个 bean,则 Spring 容器会创建该 bean 定义的类的一个且仅一个实例。
单例作用域是 Spring 中的默认作用域。(也就是说,如果无特别声明作用域时,该bean就是单例的)
二、应用场景- 不必要重复创建销毁同样的实例时,可使用同一个实例进行处理多个请求,而节省资源。
- 在多个请求中共享bean的某些资源。
如dao层主要功能就是去执行SQL与数据库交互数据,对于每次交互来说,实例的本质是不会变化。如果每次执行一个SQL就要实例化一个新的bean实例,那无疑就是在浪费资源(可联想数据连接池,其实让连接可以重复使用)
三、基于xml假设有多个service类注入一个dao类
Dao:
Service:
在多个service中请求注入SingletonDao时
这样子在三个service就会获得同一个singletonDao实例。
当然在这里的三个Service也都是单例的(默认单例),所以在Controller层请求时也是相同的道理
四、基于注解创建service类,这个类中有一个属性,以及一个方法,每次调用这个方法将会进行自增。
@Service
public class SingletonService {
private int flag = 0;
public int add(){
System.out.println("当前值为:"+flag);
this.flag++;
return flag;
}
}
在Controller进行请求注入Service
@RestController
public class SingletonController {
@Autowired
private SingletonService singletonService;
@RequestMapping("/add")
public int add(){
return singletonService.add();
}
}
最后启动项目,在浏览器访问 http://ip:port/add 会得到一个随着你不断访问而增加的数字,即使你换个浏览器访问。
以上示例只是说明问题,在正式开发中需要考虑共享资源的安全性



