singleton
:唯一bean实例,Spring中的bean默认都是单例的。prototype
:每次请求都会创建一个新的bean实例。request
:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。session
:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。global-session
:全局session作用域,仅仅在基于Portlet的Web应用中才有意义,Spring5中已经没有了。Portlet是能够生成语义代码(例如HTML)片段的小型Java Web插件。它们基于Portlet容器,可以像Servlet一样处理HTTP请求。但是与Servlet不同,每个Portlet都有不同的会话。
- Bean容器找到配置文件中Spring Bean的定义。
- Bean容器利用Java Reflection API创建一个Bean的实例。
- 如果涉及到一些属性值,利用set()方法设置一些属性值。
- 如果Bean实现了BeanNameAware接口,调用
setBeanName()
方法,传入Bean的名字。
- 如果Bean实现了BeanClassLoaderAware接口,调用
setBeanClassLoader()
方法,传入ClassLoader对象的实例。 - 如果Bean实现了BeanFactoryAware接口,调用
setBeanClassFacotory()
方法,传入ClassLoader对象的实例。 - 与上面的类似,如果实现了其他*Aware接口,就调用相应的方法。
- 如果有和加载这个Bean的Spring容器相关的BeanPostProcessor对象,执行
postProcessBeforeInitialization()
方法。 - 如果Bean实现了InitializingBean接口,执行
afeterPropertiesSet()
方法。 - 如果Bean在配置文件中的定义包含init-method属性,执行指定的方法。
- 如果有和加载这个Bean的Spring容器相关的BeanPostProcess对象,执行postProcessAfterInitialization()方法。
- 当要销毁Bean的时候,如果Bean实现了DisposableBean接口,
执行destroy()方法
。 - 当要销毁Bean的时候,如果Bean在配置文件中的定义包含destroy-method属性,执行指定的方法。
Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略
,因此可以说Spring容器中的Bean本身不具备线程安全的特性
,但是具体还是要结合具体scope的Bean去研究。
结合上面提到的Spring bean 的作用域(scope)
- 对于
prototype作用域的Bean
,每次都创建一个新对象,也就是线程之间不存在Bean共享,因此不会有线程安全问题。 - 对于
singleton作用域的Bean
,所有的线程都共享一个单例实例的Bean,因此是存在线程安全问题的。但是如果单例Bean是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Controller类、Service类和Dao等,这些Bean大多是无状态的,只关注于方法本身。
有状态Bean
(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的
。无状态Bean
(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的
。
线程安全这个问题,要从单例与原型Bean分别进行说明。
对于有状态的bean
(比如ModelAndView),就需要自行保证线程安全,最浅显的解决办法就是将有状态的bean的作用域由“singleton”改为“prototype”
。也可以采用ThreadLocal
解决线程安全问题,为每个线程提供一个独立的变量副本,不同线程只操作自己线程的副本变量。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。
同步机制
:采用了“时间换空间”的方式,仅提供一份变量,不同的线程在访问前需要获取锁,没获得锁的线程则需要排队。ThreadLocal
:采用了“空间换时间”的方式。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。
课间休息,又来秀一下来自咱们群里同学的搬砖工地,坐标:济南 遥墙机场。
作者:對你何止一句钟意
=======================================================================================
流程说明:
- 客户端(浏览器)发送请求,直接请求到DispatcherServlet。
DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler
。- 解析到对应的
Handler
(也就是我们平常说的Controller控制器
)。 - HandlerAdapter会根据Handler来调用真正的处理器(
对应的接口
)来处理请求和执行相对应的业务逻辑。 - 处理器处理完业务后,会返回一个ModelAndView对象,Model是返回的数据对象,View是逻辑上的View。
- ViewResolver(视图解析器)会根据逻辑View去查找实际的View。
- DispatcherServlet把返回的Model传给View(视图渲染)。
- 把View返回给请求者(浏览器)。
DispatcherServlet
:前端控制器
。用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由它调用其它组件处理用户的请求,dispatcherServlet的存在降低了组件之间的耦合性,系统扩展性提高。由框架实现HandlerMapping
:处理器映射器
。HandlerMapping负责根据用户请求的url找到Handler即处理器,springmvc提供了不同的映射器实现不同的映射方式,根据一定的规则去查找,例如:xml配置方式,实现接口方式,注解方式等。由框架实现Handler
:处理器
。Handler 是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。由于Handler涉及到具体的用户业务请求,所以一般情况需要程序员根据业务需求开发Handler。