一、Spring的简介
1、spring的起源和背景
Rod Johson在2002年编著的《Expert one to one J2EE design and development》一书中,对Java EE正统框架臃肿、低效、脱离现实的种种现状提出了质疑,并积极寻求探索革新之道。以此书为指导思想,他编写了interface21框架,这是一个力图冲破Java EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。
Spring致力于J2EE应用的各层的解决方案,而不是仅仅专注于某一层的方案。可以说Spring是企业应用开发的“一站式”选择,并贯穿表现层、业务层及持久层。然而,Spring并不想取代那些已有的框架,而与它们无缝地整合。
spring的设计目标:遵循一系列的接口标准,这样的好处是只需要简单的Java对象或者Javabean就能进行Java EE开发,这样开发的入门、测试、应用部署都得到了简化。
2、spring简介
Spring是一个开源的用于简化采用Java语言开发企业级程序的一个分层的框架。(一站式集成框架)
Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。
二、Spring作用
◆方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。
◆AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。
◆声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
◆方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。
◆方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hession、Quartz)等的直接支持。
◆降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。
◆Java 源码是经典学习范例
优点:
1.简洁,快捷,一个高效的开发框架
2.有很好DI(依赖注入),代码侵入比较低,代码污染比较低
3.它是兼容其它框架的,封装了其他框架的使用,降低了我们开发的难度
4.解耦,javabean 代替传统EJB。
三、Spring的核心模块
Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式,组成 Spring 框架的每个模块(或组件)都可以单独存在,或者与其他一个或多个模块联合实现。每个模块的功能如下:
1)Spring Core:核心容器,BeanFactory提供了组件生命周期的管理,组件的创建,装配,销毁等功能
SpringContext:ApplicationContext,扩展核心容器,提供事件处理、国际化等功能。它提供了一些企业级服务的功能,提供了JNDI,EJB,RMI的支持。
2) Spring AOP:提供切面支持
3) Spring DAO:提供事务支持,JDBC,DAO支持
4) Spring ORM:对流行的O/R Mapping封装或支持
5) Spring Web:提供Web应用上下文,对Web开发提供功能上的支持,如请求,表单,异常等。
6) Spring Web MVC:全功能MVC框架,作用等同于Struts。
7)核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
四、Spring的注解方式
注解的作用:1、生成文档 2 .跟踪代码依赖性 3.在编译时进行格式检查
@Component : 是所有受Spring 管理组件的通用形式,@Component注解可以放在类的头上,@Component不推荐使用。
@Controller:标识这个类是控制器,对应表现层的Bean 通常作用在控制层
@Autowired :读取 它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作 注释标注在 Setter 方法上
@RequestMapping:转发
@Repository : 表示这是dao的实现类
@Service:服务层 ,对应的业务bean层 通常作用在业务层
@ContextConfiguration:要解析的spring.xml文件
@RunWith :SpringJUnit4ClassRunner.class
@Transactional:事物处理
@Annotation:为并发编程准备
@Immutable 类是不可变的
@ThreadSafe 表示这个类是线程安全的
@NotThreadSafe表示这个类不是线程安全的
五、Spring中bean的注入的三种方式
1、set的注入
本质上是通过set方法来去注入值
bean标签里的class对应着对象的类路径也就是完全限定名,以便spring来去查找加载这个类 id是我们给这个bean赋予的名字,bean工厂根据这个名字来获取这个bean
里面的属性放在property里面,property里的name对应着bean的属性也就是成员变量的名字 value对应着是我们给这个成员变量赋予的值
如果是数组的话,在property里面创建list标签,在list里面放入多个value值,逗号无效,只跟value的标签个数有关
(1)属性的注入:八大基本数据类型及包装类型,String类型
(2)注入对象
(3)集合类型的注入
a)<list>: 该标签用来装配可重复的list值。
b)<set>: 该标签用来装配没有重复的set值。
c)<map>: 该标签可用来注入键和值可以为任何类型的键值对。
d)<props>: 该标签支持注入键和值都是字符串类型的键值对。properties文件
2、构造器注入
通过有参的构造函数来去注入值
bean标签里的class对应着对象的类路径也就是完全限定名,以便spring来去查找加载这个类 id是我们给这个bean赋予的名字,bean工厂根据这个名字来获取这个bean
里面放入constructor-arg标签,value值放入对应的属性值(即类的有参构造函数的参数)
当构造函数里的参数不止一个或者有其他类型
创建多个constructor-arg标签,指定type,如果不指定默认是String类型,设置index,决定参数的顺序
3、接口注入(不常使用)
六、Spring的Bean有以下五种作用域(scope=“singleton”)
1.singleton:单例模式,在整个Spring IoC容器中,使用singleton定义的Bean将只有一个实例(默认);
2.prototype:原型模式,每次通过容器的getBean方法获取prototype定义的Bean时,都将产生一个新的Bean实例;
3.request:对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。只有在Web应用中使用Spring时,该作用域才有效;
4.session :对于每次HTTP Session,使用session定义的Bean豆浆产生一个新实例。同样只有在Web应用中使用Spring时,该作用域才有效;
5.global session :每个全局的HTTP Session,使用session定义的Bean都将产生一个新实例。典型情况下,仅在使用portlet context的时候有效。同样只有在Web应用中使用Spring时,该作用域才有效;
注:其中比较常用的是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框架中单例beans是线程安全的吗?
不是,Spring框架中的单例beans不是线程安全的。
附上一篇对bean的作用域比较详细的文章:https://www.cnblogs.com/yangjian-java/p/6703489.html
七、Spring配置文件的加载方式
1.利用ClassPathXmlApplicationContext,这种方式配置文件应该放在类包同路径下
2.利用FileSystemXmlApplicationContext,这种方法可以将配置文件放在工程的直接目录下
3.显式给出配置文件的绝对路径,我们假定配置文件位于工程主目录中的conf文件夹中
4.利用FileSystemResource,可以将配置文件放在工程直接目录下
5.显式给出配置文件的绝对路径,我们假定配置文件位于工程主目录中的conf文件夹中
八、Spring之IOC(控制反转)
8、1、IoC是什么
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:
●谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。
●为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。
用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:
当有了IoC/DI的容器后,在客户端类中不再主动去创建这些对象了,如图所示:
8、2、 IoC能做什么
IoC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。
其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
8、3、IoC和DI
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。
九、Spring之AOP(面向切面编程)
链接:http://jinnianshilongnian.iteye.com/blog/1474325
十、声明式事务的特点及传播属性
声明式事务的特点:
Spring的声明式事务顾名思义就是采用声明的方式来处理事务
传播属性:采用声明的方式来处理事务
propagation_required:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择
propagation_supports:支持当前事务,如果当前没有事务,就以非事务方式执行
propagation_mandatory:支持当前事务,如果当前没有事务,就抛出异常
propagation_requires_new:新建事务,如果当前存在事务,把当前事务挂起
propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
propagation_never:?以非事务方式执行,如果当前存在事务,则抛出异常
propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作
十一、谈谈spring的事务
事物管理是保证数据操作的事务性即,原子性,一致性,隔离性,持久行,即所谓的acid
Spring框架对事务管理的支持改变了传统上认为J2EE应用需要应用服务器的观点,Spring可以将任意Java Bean纳入事务管理, 同时Spring事务管理也不依赖特定的事务资源。
spring提供了几个关于事务处理的类:TransactionDefinition 事务属性定义, 包含了事务的静态属性,比如:事务传播行为、超时时间等等
TranscationStatus //代表了当前的事务,可以提交,回滚。
PlatformTransactionManager //是spring提供的用于管理事务的基础接口,用于执行具体的事务操作,其下实现有一个抽象类
AbstractPlatformTransactionManager。
相关的事务管理类例如DataSourceTransactionManager等都是这个抽象类的子类。
事务隔离级别:隔离级别是指若干个并发的事务之间的隔离程度
事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。所谓事务传播行为就是多个事务方法相互调用时,
事务如何在这些方法间传播。
spring提供的事务管理可以分为两类:编程式的和声明式的。编程式的,比较灵活,但是重复的代码比较多,直接或间接使用底层持久化api;
声明式的比编程式的更灵活,声明式事务管理是通过Spring AOP实现的,其中的事务通知由元数据(XML或注解)驱动。这也是我们常采用的事务管理方式。