Spring
Spring概述
什么是Spring
Spring是一个开放源代码的设计层面框架,
他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
Spring是于2003 年兴起的一个轻量级的Java 开发框架
简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。
spring特点
-
方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 -
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,
许多不容易用传统OOP实现的功能可以通过AOP轻松应付。 -
声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,
通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 -
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。 -
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。 -
降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)
提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。 -
Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
IOC
什么IOC
IOC: Inversion of Control(控制反转)
控制反转:将对象的创建权反转给(交给)Spring。
传统开发模式
业务和实现类过于紧密,底层业务要修改源代码
通过工厂可以实现,接口与实现业务的分离
在工厂内部使用配置文件加载
使用spring-IOC
- 添加jar包
- 创建配置文件
通常名称起为applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
- 添加配置文件
- 测试使用
IOC与DI
DI 依赖注入
前提必须有IOC的环境
Spring管理这个类的时候才能将类的依赖的属性值注入(设置)进来
依赖注入:给spring管理类当中依赖的属性,通过配置文件进行赋值的过程
传统方式
DI方式
1.实现类当中的属性要提供set方法
2.在配置文件当中配置依赖注入
测试
Spring的工厂类
- BeanFactory
老版本使用方式
当调用getBean的时候才会创建实例对象 - ApplicationContext
新版本使用方式
当加载配置文件时候就会创建实例对象 - ApplicationContext实现类
- ClassPathXmlApplicationContext
加载类路径下的配置文件
- FileSystemXmlApplicationContext
加载文件系统下的配置文件
- ClassPathXmlApplicationContext
Bean相关配置
名称与标识
id:使用了约束中的唯一约束。里面不能出现特殊字符的
name:没有使用约束中的唯一约束。里面可以出现特殊字符。
设置对象的生命周期方法
init-method
Bean被初始化的时候执行的方法
destroy-method
Bean被销毁的时候执行的方法(Bean是单例创建,工厂关闭)
Bean的作用范围的配置
scope
- singleton 默认的,Spring会采用单例模式创建这个对象。
- prototype 多例模式。
- request 应用在web项目中,Spring创建这个类以后,将这个对象存入到request范围中。
- session 应用在web项目中,Spring创建这个类以后,将这个对象存入到session范围中
- globalsession 应用在web项目中,必须在porlet(基于Java的Web组件,子域名)环境下使用。但是如果没有这种环境,相对于session。
工厂实例化的方式
- 无参构造-默认
- 静态工厂实例化
- 实例工厂实例化
分模块配置
在加载时,添加多个配置文件名称
在一个配置文件当中引入另一个配置文件
Spring属性注入
- 构造方法的方式的属性注入
- Set方法的属性注入
- Set方法设置对象类型的属性
- P名称空间的属性注入
使用p名称空间,就不需要写那那么多的property
使用时,要添加名称空间
xmlns:p="http://www.springframework.org/schema/p"
- spEL表达式的属性注入
- 集合类型属性注入
1. 数组
2. List集合
3. Set集合
4. Map集合
IOC注解方式
在spring4之后,想要使用注解形式,必须得要引入aop的包
在配置文件当中,还得要引入一个context约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
配置组件扫描
哪个包下的类型使用组合扫描
在类开上添加注解
使用注解注入属性
可以不用提供set方法,直接在直接名上添加@value("值")
如果提供了set方法,在set方法上添加@value("值");
IOC注解详解
@Component
修改一个类,将这个类交给Spring管理 相当于在配置文件当中配置
< bean id="" class="">
@Component三个衍生注解
为了更好的进行分层,Spring可以使用其它三个注解,功能类似
目前使用哪一个功能都一样, 后期可能会添加一些属于各自的属性
- @Controller web层
2. @Service service层
3. @Repository dao层
属性注入
- @Value:设置普通属性值
- @Autowired
设置对象类型的属性值
直接使用这种方式,是按照类型完全属性注入
不需要在注解上使用id名称
习惯是按照名称完成属性注入
必须让@Autowired注解与@Qualifier一起使用
单独使用@Resource
- @PostConstruct:初始化方法
- @PreDestroy:销毁方法
- @scope:作用范围
XML与注解比较
XML可以适用任何场景 ,结构清晰,维护方便
注解不是自己提供的类使用不了,开发简单方便
XML与注解整合开发
XML管理Bean
注解完成属性注入
使用过程中, 可以不用扫描,扫描是为了类上的注解
在没有扫描的情况下, 使用属性注解@Resource @Value @Autowired @Qulifier
<context:annotation-config/>
AOP
AOP简介
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,
通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
开发存在的问题
JDK动态代理
cglib动态代理
Cglig是一个第三方开源代码 生成类库,动态添加类的属性和方法。
在spring的核心包当中已经引入了cglib
采用的是继承方式来产生的代理对象
Spring的AOP简介
AOP思想最早是由AOP联盟组织提出的
Spring使用这种思想最好的框架
AspectJ
Spring的AOP有自己的实现方式,但是这种方式非常繁琐
AspectJ 是一个AOP的框架
Spring放弃了自己传统的方式 ,引入AspectJ作为自身AOP的开发
AOP相关术语
-
Joinpoint:连接点
可以被拦截到的方法
能够被增强的方法,这些方法就可以称为是连接点
-
Pointcut:切入点
真正被拦截的方法
真正被增加的方法
-
Advice:通知
增加的内容,通常都是封装成一个方法, 这个方法我们就称为通知
-
Introduction:引介
类层面的增加
给原有的类添加一些新的属性方法
在开发中通常都是给方法进行增加 -
Target:被增加的对象
-
Weaving:织入
将通知应用到目标对象的过程 -
Proxy:代理对象
-
Aspect:切面
多个通知和多个切入点的集合
AOP通知类型
前置通知
在目标方法执行之前进行操作
后置通知
在目标方法执行之后 进行操作
环绕通知
在目标方法执行之前 和之后进行操作
public Object arount()
异常抛出通知
在程序出现异常时进行操作
最终通知
无论代码是否有异常,都会执行
AOP切入点表达式
基于execution函数完成
【访问修饰符】 方法返回值 包名.类名.方法名(参数)
public com.myxq.demo2.GoodsDaoImpl.save(..)
参数为任意参数
* com.myxq.demo2.GoodsDaoImpl.save(..)
* 任意类型
* com.myxq.demo2.GoodsDaoImpl+.save(..)
+ 当前类和子类
* com.myxq..*.*(..)
com.myxq包以及子包下面所有类的所有方法
AOP注解方式ApsectJ开发
- 引入Jar包
- 引入配置文件
- 编写切面类配置
- 使用注解的AOP对象目标类进行增强
在配置文件中开启以注解形式进行AOP开发
在切面类上添加注解
- 注解AOP通知类型
@Before前置通知
@AfterReturning后置通知
没有返回值
有返回值
@Around环绕通知
@AfterThrowing异常抛出通知
没有获取异常信息
获取异常信息
@After最终通知
AOP的注解切入点的配置
有时候一个方法要添加前置通知对又要添加异常通知,又要添加最终通知
可以在切面当中定义好切入点
在通知当中直接使用定义好的切入点表达式
定义多个切入点
一个通知同时定义到多个方法当中
当使用接口时与不使用接口内部代理区别
使用接口
spring-JDBC模板
Spring的JDBC的模板
Spring是EE开发的一站式的框架,有EE开发的每层的解决方案。
Spring对持久层也提供了解决方案:ORM模块和JDBC的模板。
Spring提供了很多的模板用于简化开发
- JDBC
org.springframework.jdbc.core.jdbc.jdbcTemplate - Hibernate
orm.springframework.orm.hibernamte.HibernateTemplate
JDBC模板使用的入门
- 引入jar包
spring开发基本jar包
数据库驱动 - 创建数据库和表
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);
Spring的JDBC模板的jar包
- 使用JDBC的模板
将连接池和模板交给Spring管理
配置文件配置Bean
使用jdbcTemplate注解插入数据
使用开源连接池
-
DBCP
引入jar包
配置DBCP连接池
-
C3P0
引入jar包
配置
-
DRUID
引入jar包
配置
使用属性文件配置数据库连接信息
- 创建属性文件
- 配置文件中引入属性文件
< bean>方式
< context/>
JDBC模板CRUD操作
插入操作
删除操作
更新操作
查询操作
查询某一个字段
查询返回对象的集合
事务
事务概述
什么事务
逻辑上的一组操作,组成这组操作的各个单元,要么全都成功,要么全都失败。
事务的特性
原子性:事务不可分割
一致性:事务执行前后数据完整性保持一致
隔离性:一个事务的执行不应该受到其他事务的干扰
持久性:一旦事务结束,数据就持久化到数据库
如果不考虑隔离性引发安全性问题
读问题
脏读 :一个事务读到另一个事务未提交的数据
不可重复读 :一个事务读到另一个事务已经提交的update的数据,导致一个事务中多次查询结果不一致
虚读、幻读 :一个事务读到另一个事务已经提交的insert的数据,导致一个事务中多次查询结果不一致。
写问题
丢失更新
解决读问题
设置事务的隔离级别
- Read uncommitted :未提交读,任何读问题解决不了。
- Read committed :已提交读,解决脏读,但是不可重复读和虚读有可能发生。
- Repeatable read :重复读,解决脏读和不可重复读,但是虚读有可能发生。
- Serializable :解决所有读问题。
Spring的事务管理的API
PlatformTransactionManager
PlatformTransactionManage:平台事务管理器 是一个接口,下面有两个实现类
- DataSourceTransactionManager
底层使用JDBC管理事务 - HibernateTransactionManager
底层使用Hibernate管理事务
TransactionDefinition
事务定义信息:用于定义事务的相关的信息,隔离级别、超时信息、传播行为、是否只读
TransactionStatus
事务状态:用于记录在事务管理过程中,事务的状态的对象。
事务管理的API的关系
Spring进行事务管理的时候,首先平台事务管理器根据事务定义信息进行事务的管理,
在事务管理过程中,产生各种状态,将这些状态的信息记录到事务状态的对象中。
Spring的事务的传播行为
什么是传播行为
一个业务方法当中,调用另一个业务的方法
Spring中提供了七种事务的传播行为
保证多个操作在同一个事务中
- PROPAGATION_REQUIRED
默认值,如果A中有事务,使用A中的事务,如果A没有,创建一个新的事务,将操作包含进来 - PROPAGATION_SUPPORTS
支持事务,如果A中有事务,使用A中的事务。如果A没有事务,不使用事务。 - PROPAGATION_MANDATORY
如果A中有事务,使用A中的事务。如果A没有事务,抛出异常。
保证多个操作不在同一个事务中
- PROPAGATION_REQUIRES_NEW
如果A中有事务,将A的事务挂起(暂停),创建新事务,只包含自身操作。如果A中没有事务,创建一个新事务,包含自身操作。 - PROPAGATION_NOT_SUPPORTED
如果A中有事务,将A的事务挂起。不使用事务管理。 - PROPAGATION_NEVER
如果A中有事务,报异常。
嵌套式事务
PROPAGATION_NESTED
嵌套事务,如果A中有事务,按照A的事务执行,执行完成后,设置一个保存点
执行B中的操作,如果没有异常,执行通过,如果有异常,可以选择回滚到最初始位置,也可以回滚到保存点
Spring事务管理
- 搭建Spring事务管理环境
1.创建AoccuntDao
2.实现Dao接口
3.把Dao交给Spring管理
5.在Dao中注入数据源
在DAO当中注入jdbc模板,要保证dao继承了JdbcDaoSupport
继承之后, 就有了datasource的set方法,就可以注入了
Dao继承JdbcDaoSupport
DAO注入JDBC模板
6.创建Account业务
7.配置service 交给spring 并注入dao
8.测试
- 添加事务
编程式事务
需要手动编写代码
步骤
- 配置平台事务管理器
<!--配置事务管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
- Spring提供了事务管理的模板类
<!--配置事务管理模板-->
<bean id="transactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
- 在业务层注入事务管理的模板
- 编写事务管理的代码
声明式事务
XML方式声明事务管理
1.引入aop的开发包
2.配置事务管理器
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
3.AOP的配置
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
配置
注解方式声明事务管理
配置事务管理器
开启注解事务
在业务层添加注解