Spring框架资料
一、Spring介绍
1.Spring是什么
1.spring是一个开源框架
2.spring为简化企业级应用开发而生,使用Spring可以使简单的 javaBean实现以前只 有EJB才能实现的功能.
3.spring是一个IOC(DI)
IOC
控制反转:
将组建对象的控制权从代码本身转移到外部容器
组件化的思想:分离关注点,使用接口,不在关注实现.
依赖的注入:将组建的构建和使用分开
目的:解耦合,实现每个组件时只关注组件内部的情况,
要点:明确定义组件间的接口
控制反转建立在工厂模式上:
工厂模式:根据我们提供的我们所需要的对象实例的描述,为我们返回产品
1.产品的规范
2.产品
3.工厂
4.客户端/调用
使用IOC的好处:
解耦合
更利于程序的扩展
4.Sprng是一个AOP容器框架
5.Spring是一个粘合剂(大管家:用于整合各种框架)
2.具体描述Spring
1.轻量级:spring是非侵入性的 基于spring开发的应用中的对象可以不依赖于s pring 的api
轻量级:不需要继承或实现任何spring的接口或类
2.依赖注入(DI--dependency injection.IOC--Inversion of Control)
3.面向切面编程(AOP--aspect oriented programming)
4.容器:spring是一个容器,因为他包含并且管理应用对象的生命周期
5.框架:spring实现了使用简单的组件组合成一个复杂的应用,在spring中可以使用xml和java注解组合这些对象
6.一站式:在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库,实际上spring自身也提供了展现层的SpringMVC和持久层的SpringJDBC
3.Spring体系结构
Spring RunTime
1.底层核心容器 core Control
1.Beans javaBean
2.core 核心部分
3.comtext 上下文
4.SpEL 表达式
2.Aspects
3.AOP
4.instrumentation
5.Messaging
6.整合数据Data Access/Integration
1.JDBC
2.ORM
3.OXM
4.JMS
5.Transactions
7.整合Web
1.WebSocket
2.Servlet
3.Web
4.Portlet
8.Test
二、IOC设置注入
1.<bean>标签--指向一个类
class属性:需要注入的类的全路径名
id属性:生成的对象的名称
<property>标签
name属性:对应对象中set方法后面的属性名称部分首字母改成小写(需要添加 set方法为属性设值)
value属性/标签:预设置的值
2. Application
Application是一个Spring容器 供Spring初始化 得到javabean对象
通过ClassPathXmlApplicationContext方法获取到spring容器对象
通过getBean("id名称")的方法获取到指定id(javabean)的对象
3.为什么叫IOC
反转控制,将由客户端创建的对象交给容器去创建
默认调用类的无参构造函数
三、DI依赖注入
1.属性注入
属性注入即通过setter方法注入Bean的属性值或依赖的对象。
属性注入使用<property>元素,使用name属性指定Bean的属性名称,value属性或 <value>子节点指定属性值,属性注入是实际应用中最常用的注入方式
a.非引用注入
8种基本数据类型
<property>元素的引用属性用value来指定
b.引用注入
组成应用程序的Bean通常需要互相协作以完成应用程序的功能,要使Bean能 够互相访问,就必须在Bean配置文件中指定对Bean的引用
<property>元素的引用属性用ref来指定
四、构造器注入
通过构造方法注入Bean的属性值,或依赖的对象,它保证了Bean实例在实例化后就可以使 用,构造器注入在<constructor-arg>元素里声明属性
C.非引用注入
属性注入即通过setter方法注入Bean的属性值或依赖的对象。
d.引用注入
javaBean
在Bean的配置文件中,可以通过<ref>元素或者ref属性为Bean的属性或构造 器参数指定对Bean的引用,也可以在属性或构造器里包含Bean的声明,这样的 Bean称为内部Bean
五、集合属性注入
在Spring中可以通过一组内置的XML标签(例如:<list><set>或<map>)来配置集合属性:
配置java.util.List类型的属性,需要<list>标签,在标签里包含一些元素,这些标签可以通过<value>指定简单的常量值,通过<ref>指定对其他Bean的引用,通过<bean>指定内置Bean定义,通过<null/>指定空元素,甚至可以内嵌其他集合
数组的定义和List一样,都使用<list>配置java.util.Set需要使用<set>标签,定义元素的方法与List一样:
java.util.Map通过<map>标签定义,<map>标签里可以使用多个<entry>作为字标签,每个条目包含一个键和一个值;
必须在<key>标签里定义键,因为键和值的类型没有限制,所以可以自由的为他们制定<value>,<ref>,<bean>,或<null/>元素;
可以将map的键和值作为<entry>的属性定义;简单常量使用key和value来定义;Bean引用通过key-ref和value-ref属性定义;
使用<props>定义java.util.Properties,该标签使用多个<prop>作为子标签,每个<prop>标签必须定义key属性
六、工厂类注入
时间类属性注入
例1: <bean id="dateFormat" class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd"> </bean>
<bean id="dateType" class="cn.service.DateType"> <property name="dateValue"> <bewan factory-bean="dateFormat" factory-method="parse"> <constructor-arg value="2016-12-31"/> </bean> </property> </bean>
|
七、内部bean
内部bean作为注入,没有id名称,不能被外部引用
例2: <bean id="student" class="entity.Student"> <propert name="book"> <bean class="entity.Book" > <property name="bookName" value="java编程思想"/> </bean> </property> </bean> |
八、bean的自动装配
XML配置里的Bean自动装配
SpringIOC容器可以自动装配Bean,需要做的仅仅是在Bean的autowire属性里指定自动装配的模式
byName(根据名称自动装配):
必须将目标Bean的名称和属性名设置的完全相同
缺点:在Bean配置文件里设置autoWire属性进行自动装配将会装配Bean的所有属性,然而若 值希望装配个别属性时,autowire属性就不够灵活了
autowire属性要么根据类型自动装配,要么根据名称自动装配,两者不能兼而有之
手动局部装配
1.<bean>标签的autowire属性直接配置自定义属性的名字自动装配
2.根据数据类型装配byType
自动全局装配
在头部声明最后加上属性default-autowire="byName|byType"
九、继承Bean配置
spring允许继承bean的配置,被继承的bean成为父bean,继承这个bean的bean称为子 bean
子bean从父bean中继承配置,包括bean的属性配置
子bean也可以覆盖从父bean继承过来的配置
父bean可以作为配置模板,也可以作为bean实例,若想把父bean作为末班
可以设置<bean>的abstract属性为true,这样spring将不会实例化这个bean
子bean 继承用<bean>标签中的parent属性指定其父类
十、bean的作用域
在spring中,可以在<bean>元素的scope属性里设置bean的作用域
默认情况下是单例模式,spring只为每个在IOC容器里声明的bean创建唯一实例,整个IOC容器范围内都能共享该实例,所有后续的getBean()调用和Bean引用都将返回这个唯一的Bean实例,该作用域被称为singleton,它是所有Bean的默认作用域
类别 | 说明 |
Singleton | 在SpringIOC容器中仅存在一个Bean实例,Bean以单实例的方式存在 |
prototype | 每次调用getBean()时都会返回一个新的实例 |
request | 每次Http请求都会创建一个新的Bean,该作用域仅适用于WebApplicationConntext环境 |
session | 同一个HttpSession共享一个Bean,不同的HttpSession使用不同的Bean该作用域仅适用于WebApplicationContext环境 |
十一、使用外部属性文件
在配置文件里配置Bean时,有时候需要再Bean的配置里混入系统部署的细节信息,例如文件路径,数据源配置信息等
而这些部署细节实际上需要和Bean配置相分离
Spring提供了一个PropertyPlaceholderConflgurer的BeanFactory后置处理器,
这个处理器允许用户将Bean配置的部分内容外移到属性文件中,可以在Bean配置文件里使用形式为${var}的变量,
PropertyPlaceholderconflgurer从属性文件里加载属性,并使用这些属性来替换变量
spring4.0以后加入了 <context:property-placeholder>标签
可以使用其中的location="classpath:jdbc.properties"属性方式加载
十二、使用注解配置
1.使用注解配置需要加入spring-aop的包与头部命名空间
2.四个注解
1.Component是一个泛化的概念,仅仅表示一个组件<Bean>.可以作用在任何层次
2.@Repository通常作用在持久化层,但是目前该功能与Component相同
3.@Service通常作用在业务层,是目前该功能与Component相同
4.@controller通常作用在控制层,是目前该功能与Component相同
这四个注解Spring会自动创建响应的BeanDefinition对象,并注册到ApplicationContext中,这些类就成了Spring受管组件.这四个注解除了作用于不同层次的类,其使用方式与@Component是完全相同的
3.自动扫描包
例: <!--自动扫描需要配置aop的jar包--> <!--并加入头声明命名空间(在xsi:schemaLocation上方) --> xmls:context="http://www.springframeword.org/schema/context 在最后一行加入: http://www.springframeword.org/schema/context http://www.springframeword.org/schema/context/spring-context-4.0.xsd <context:component-scan base-package="cn.javaa.service"/>
|
4.@Resource
@Resource默认按照ByNam自动注入,由J2EE提供,需要导入包javax.annotation.RESOURCE.@Resource有两个重要的属性,name和Type
而Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型
所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略,如果既不指定name
也不指定type这时将通过反射机制使用byName自动注入策略
注:最好是将@Resource放在stter方法上,因为这样更符合面向对象的思想.通过set、get去操作属性,而不是直接去操作属性
@Resource装配顺序
@AutoWired 按类型注入注解
@Qualifier 按名字注入注解
十三、AOP
1.静态代理模式
在不编写原有代码的情况下改变原有代码
1.实现接口2.调用接口
2.前端通知(增强)
3.后端通知
a.通知类,普通实现接口
b.业务类、业务方法
c.配置:将业务、通知 纳入springIOC容器
定义切入点(一端)、定义通知类(另一端)、通过pointcut-ref将两端连起来
4.异常通知(增强)
根据异常通知接口的定义可以发现,异常通知的实现类 必须编写以下方法:
void afterThrowing([Method,args,target],ThrowableSubclass)
这个方法的参数有两种情况:
a.public void afterThrowing(ThrowableSubclass);
b.public void afterThrowing(Method,args,target,ThrowableSubclass)
5.环绕通知(增强)
6.最终通知(增强)
7.spring AOP的配置
例:切入点:连接点的查询条件 <aop:config> <!--切入点表达式,符合该表达式的方法可以被织入增强处理--> <aop:pointcut id="pointcut" expression="execution(publiv void addNewUser(entity.User))"/> </aop:config> |
表达式匹配规则举例:
public * addNewUser(entity.User); | "*" 表示匹配所有类型的返回值 |
public void *(entity.User); | "*" 表示匹配所有方法名 |
public void addNewUser(..); | ".."表示匹配所有参数个数和类型 |
*com.service.*.*(..); | 匹配com.service包下所有类的所有方法 |
*com.service..*.*(..); | 匹配com.service包下及其子包所有类的所有方法 |
例: 织入:在切入点插入增强处理 <!--根标签--> <aop:config> <!--切入点的定义--> <aop:pointcut id="pointcut" expression="execution(publiv void addNewUser(entity.User))"/> <!--ref:调用增强处理的对象userServiceLogger--> <aop:aspect ref="userServiceLogger"> <!-- 前置增强处理 method属性:被织入的方法 pointcut-ref属性配置切入点要与id保持一致--> <aop:before method="before" pointcut-ref="pointcut"></aop:before> <!-- 后置增强处理 returning属性指定需要注入返回值的属性名为result--> <aop:after-returning method="afterReturning" pointcut-ref="pointcut"returning="result"/> </aop:aspect> </aop:config>
|
十四、注解完成声明式事务
目标:通过事务使一下事务要么全成功,要么全失败
1.jar包
spring-tx.jar 事务支持
ojdbc.jar 数据库连接
commons-dbcp.jar 连接池数据源
commons-pool.jar 连接池
spring-jdbc.jar 数据库连接
aopalliance.jar aop支持
2.在数据库配置中增加对事务的支持
1.事务管理器相关引入 例: <bean id="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="数据源dataSource"></property> </bean> 2.配置事务管理器 <tx:annotation-driven transaction-manager="txManager"/> 3.在需要成为事务的方法前使用@Transactional注解声明事务 例: @Transactional(readOnly=false)//声明这个方法不是只读方法 public Integer addStudent(Student stu){ //查看学生是否存在 //增加学生 return studentDao.addStudent(Student); } |
3.事务属性详解:
1.概述
事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
Spring Framework对事务管理提供了一致的抽象,其特点如下:
为不同的事务API提供一致的编程模型,比如JTA(Java Transaction API), JDBC, Hibernate, JPA(Java Persistence API和JDO(Java Data Objects)
支持声明式事务管理,特别是基于注解的声明式事务管理,简单易用
提供比其他事务API如JTA更简单的编程式事务管理API
与spring数据访问抽象的完美集成
2.事务管理方式
声明式事务管理建立在AOP之上的。
其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,
只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。
3.自动提交(AutoCommit)与连接关闭时的是否自动提交
默认情况下,数据库处于自动提交模式。每一条语句处于一个单独的事务中,在这条语句执行完毕时,如果执行成功则隐式的提交事务,如果
执行失败则隐式的回滚事务。
对于正常的事务管理,是一组相关的操作处于一个事务之中,因此必须关闭数据库的自动提交模式。不过,这个我们不用担心,spring会将底层连接的自动提交特性设置为false。
有些数据连接池提供了关闭事务自动提交的设置,最好在设置连接池时就将其关闭。但C3P0没有提供这一特性,只能依靠spring来设置。
因为JDBC规范规定,当连接对象建立时应该处于自动提交模式,这是跨DBMS的缺省值,如果需要,必须显式的关闭自动提交。C3P0遵守这一规范,让客户代码来显式的设置需要的提交模式。
4.事务隔离级别
隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:
TransactionDefinition.ISOLATION_DEFAULT: |
这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是 TransactionDefinition.ISOLATION_READ_COMMITTED。 |
TransactionDefinition.ISOLATION_READ_UNCOMMITTED: |
该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。 |
TransactionDefinition.ISOLATION_READ_COMMITTED: |
该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。 |
TransactionDefinition.ISOLATION_REPEATABLE_READ: |
该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。 |
TransactionDefinition.ISOLATION_SERIALIZABLE: |
所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。 |
5.事务传播行为
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
TransactionDefinition.PROPAGATION_REQUIRED: |
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。 |
TransactionDefinition.PROPAGATION_REQUIRES_NEW: |
创建一个新的事务,如果当前存在事务,则把当前事务挂起。 |
TransactionDefinition.PROPAGATION_SUPPORTS: |
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 |
TransactionDefinition.PROPAGATION_NOT_SUPPORTED: |
以非事务方式运行,如果当前存在事务,则把当前事务挂起。 |
TransactionDefinition.PROPAGATION_NEVER: |
以非事务方式运行,如果当前存在事务,则抛出异常。 |
TransactionDefinition.PROPAGATION_MANDATORY: |
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。 |
TransactionDefinition.PROPAGATION_NESTED: |
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。 |
6.事务超时
所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。
默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。
事务只读属性
只读事务用于客户代码只读但不修改数据的情形,只读事务用于特定情景下的优化,比如使用Hibernate的时候。
默认为读写事务。
7.spring事务回滚规则
指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。
默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。
可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。
还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。
8.@Transactional属性
属性 | 类型 | 描述 |
value | String | 可选的限定描述符,指定使用的事务管理器 |
Propagation | enum: Propagation | 可选的事务传播行为设置 |
Isolation | enum: Isolation | 可选的事务隔离级别设置 |
readOnly | boolean | 读写或只读事务,默认读写 |
Timeout | int (in seconds granularity) | 事务超时时间设置 |
rollbackFor | Class对象数组,必须继承自Throwable | 导致事务回滚的异常类数组 |
rollbackForClassName | 类名数组,必须继承自Throwable | 导致事务回滚的异常类名字数组 |
noRollbackFor | Class对象数组,必须继承自Throwable | 不会导致事务回滚的异常类数组 |
noRollbackForClassName | 类名数组,必须继承自Throwable | 不会导致事务回滚的异常类名字数组 |
9.用法
@Transactional 可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
虽然 @Transactional 注解可以作用于接口、接口方法、类以及类方法上,但是 Spring 建议不要在接口或者接口方法上使用该注解,因为这只有在使用基于接口的代理时它才会生效。
另外, @Transactional 注解应该只被应用到 public 方法上,这是由 Spring AOP 的本质决定的。如果你在 protected、private 或者默认可见性的方法上使用 @Transactional 注解,这将被忽略,也不会抛出任何异常。
默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。