Spring 容器中的 Bean 默认是单例的,也就是说我们在使用被Spring管理的对象的时候,不需要重复创建了,从而节省空间。
举个例子:
作为一个 CRUD 攻城狮,平时开发最多的就是一个Web应用
@RestController
public class OrderController{
@Autowired
private OrderServiceImpl orderService;
@RequestMapping(value = "/hello/{orderId}",method = RequestMethod.GET)
public Order getOrder(@PathVariable("orderId")Long orderId){
return orderService.get(orderId);
}
}
@Service
public class OrderServiceImpl implements OrderService{
@Autowired
private OrderDao orderDao;
public Order get(Long orderId){
return orderDao.get(orderId);
}
}
Spring 启动后,所有的对象已经创建好放入了容器,看下图
但一个客户端发送请求时,Servlet容器创建一个线程1,我们知道一个线程对应一个方法栈,而一个方法对应一个栈帧,下图时请求过来时的栈状态
此时调用的方法对应的是栈中的一个个栈帧,栈帧中使用到了Spring 容器中的一些对象在哪?在堆中,也可以说Spring 容器中,还是上面图种描述的样子。
此时有一个客户端发送请求过来,Servlet容器为这个客户端创建一个线程2,然后调用方法,栈状态如下
此时理解一下各个栈帧中的对象共用堆中的对象,大家会不有个疑问,多个线程共用有个对象,线程怎么知道程序执行到哪了?会不会乱了?
大家还记得有程序计数器和方法区这两个东东么?!一个线程对应一个程序计数器,我们这里的两个线程各拥有一个程序计数器
比如我们线程1执行到 orderDao.get(orderId)
这行代码,线程2才执行到 orderService.get(orderId)
,此时各个部件状态状态如下图:
此时还有个问题,程序执行增么找到方法区的代码的呢?
其实很简单,我们以线程1为例来说,我们执行 getOrder
方法对应的栈帧中不是先要从Spring容器中拿到 OrderController
对象
我们既然拿到了这个对象,是不是就可以知道其对应的Class对象了(对象.getClass()),这个Class对象可以认为就是 'OrderContoller’类对应的方法区中的字节码(.class文件)。