emmm… 有些地方有可能不到位,欢迎大家共同参与吧.
争取做出一个最好的样本.
从最简单的概念开始吧:
它是一个开源的轻量级的java开发框架,它的核心功能可以应用在任何java程序中,同时它对javaWeb程序有很好的扩展,它使得java开发更加简便,通过POJO的编程模型促进了良好的编程风格
第二点就了解下这些框架的优点把,我简单点整理,直击要害
轻量级:基础版本只有2MB
控制反转(IOC):主要作用实现了松耦合,依赖被注入到对象,而不是创建.
面向切面编程(AOP):实现了系统服务和业务逻辑代码的分离
容器:帮忙管理对象的生命周期
MVC框架:一个优良的web 层框架
事务管理:提供了统一的事务接口
异常处理
接线来整理下事务,这个我觉得很爱提问的把,毕竟事务很重要的嘛
编程式事务管理:这意味着你可以通过编程的方式管理事务,这种方式带来了很大的灵活性,但很难维护。
声明式事务管理:这种方式意味着你可以将事务管理和业务代码分离。你只需要通过注解或者XML配置管理事务。
它为不同的事务API提供了统一的编程模型。
它为编程式事务管理提供了一个简单的API而非一系列复杂的事务
它支持声明式事务管理。
它可以和Spring 的多种数据访问技术很好的融合。
PROPAGATION_REQUIRED: (propagation传播_required必须)
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY: 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW: 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
第一步:发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求HandlerMapping查找 Handler( 可以根据xml配置、注解进行查找)
第三步:处理器映射器HandlerMapping向前端控制器返回Handler
第四步:前端控制器调用处理器适配器去执行Handler
第五步:处理器适配器去执行Handler
第六步:Handler执行完成给适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView(ModelAndView是springmvc框架的一个底层对象,包括Model和view)
第八步:前端控制器请求视图解析器去进行视图解析(根据逻辑视图名解析成真正的视图(jsp))
第九步:视图解析器向前端控制器返回View
第十步:前端控制器进行视图渲染( 视图渲染将模型数据(在ModelAndView对象中)填充到request域)
第十一步:前端控制器向用户响应结果
ApplicationContext提供了一种解决文档信息的方法,一种加载文件资源的方式(如图片),他们可以向监听他们的beans发送消息。另外,容器或者容器中beans的操作,这些必须以bean工厂的编程方式处理的操作可以在应用上下文中以声明的方式处理。应用上下文实现了MessageSource,该接口用于获取本地消息,实际的实现是可选的。
相同点:两者都是通过xml配置文件加载bean,ApplicationContext和BeanFacotry相比,提供了更多的扩展功能。
不同点:BeanFactory是延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用ApplicationContext。
Spring bean 表示受到Spring管理的对象,具体说来,它是被Spring框架容器初始化、配置和管理的对象。
Spring bean是在Spring的配置文件中定义(也可以通过annotation注解来定义),在Spring 容器中初始化,然后注入到应用程序中的。
因为在最早的版本中,Spring是被设计用来管理JavaBean的,所以Spring管理的对象会被称为“bean”。当然,现在Spring已经可以管理任何对象,即使它不具备默认构造器和设置方法(getter和setter)这些JavaBean的特性。然而,”Spring bean“这个术语仍然被保存了下来。
在Spring中创建的beans都是单例的beans。在bean标签中有一个属性为”singleton”,如果设为true,该bean是单例的,如果设为false,该bean是原型bean。Singleton属性默认设置为true。因此,spring框架中所有的bean都默认为单例bean。
其中比较常用的是singleton和prototype两种作用域。对于singleton作用域的Bean,每次请求该Bean都将获得相同的实例。容器负责跟踪Bean实例的状态,负责维护Bean实例的生命周期行为;如果一个Bean被设置成prototype作用域,程序每次请求该id的Bean,Spring都会新建一个Bean实例,然后返回给程序。在这种情况下,Spring容器仅仅使用new 关键字创建Bean实例,一旦创建成功,容器不在跟踪实例,也不会维护Bean实例的状态。
如果不指定Bean的作用域,Spring默认使用singleton作用域。Java在创建Java实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype作用域Bean的创建、销毁代价比较大。而singleton作用域的Bean实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将Bean被设置成prototype作用域。
曾经面试的时候有面试官问我spring的controller是单例还是多例,结果
我傻逼的回答当然是多例,要不然controller类中的非静态变量如何保证是线程安全的,这样想起似乎是对的,但是不知道(主要是我没看过
spring的源码,不知道真正的内在意图)为什么spring的controller是单例的。
先看看spring的bean作用域有几种,分别有啥不同。
spring bean作用域有以下5个:
singleton:单例模式,当spring创建applicationContext容器的时候,spring会欲初始化所有的该作用域实例,加上lazy-init就可以避免预处理;
prototype:原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理;
==下面是在web项目下才用到的=
request:搞web的大家都应该明白request的域了吧,就是每次请求都新产生一个实例,和prototype不同就是创建后,接下来的管理,spring依然在监听
session:每次会话,同上
global session:全局的web域,类似于servlet中的application
好了,上面都说了spring的controller默认是单例,那很自然就是singleton了。
为什么spring要默认是单例呢?原因有二:
1、为了性能。
2、不需要多例。
1、这个不用废话了,单例不用每次都new,当然快了。
2、不需要实例会让很多人迷惑,因为spring mvc官方也没明确说不可以多例。
我这里说不需要的原因是看开发者怎么用了,如果你给controller中定义很多的属性,那么单例肯定会出现竞争访问了。
因此,只要controller中不定义属性,那么单例完全是安全的。下面给个例子说明下:
默认单例的
改为多例的(就是在class上面加一个@Scope(“request”)):
从此可见,单例是不安全的,会导致属性重复使用。
最佳实践:
1、不要在controller中定义成员变量。
2、万一必须要定义一个非静态成员变量时候,则通过注解@Scope(“prototype”),将其设置为多例模式。
当通过spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持如下5种作用域:
singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例
prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例
request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效
session:对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效
globalsession:每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效