什么是spring
Spring是分层的javaSE/EE(一站式)轻量级框架
分层:
Sum提供的EE的三层架构,web层 业务层 数据访问层(持久层)
Struts2是web层基于MVC设计模式的框架
Hibernate是持久的ORM框架
一站式:【spring对每一层都有自己的解决方案】
Web层:springMVC
持久层:JDBC Template
业务层:spring的Bean管理
Spring的核心
Ioc(Inversion of Control) 控制反转
控制反转:将对象的创建权,交给spring完成
Aop(Aspect Oriented Programming) 面向切面编程
IOC控制反转的核心
Spring的版本:
Spring3.x和spring4.x
Spring3.2是spring3里面最高的版本
Spring3.0.2里面有依赖包:c3p0,dbcp,log4j,之后的版本就不在提供了
Spring4.x需要整合hibernate4.x
Spring优点:
方便解耦,简化开发
Spring是一个大工厂,可以将所有的对象的创建和组建的依赖关系,交给spring来管理
AOP编程的支持
Spring提供了面向切面的编程,可以方便的实现程序的增强功能 如:写让日志/权限控制。
声明式事物的支持
只需要通过配置就可以完成事务的管理,无须自己手动编写
方便程序的测试
Spring对局junit4支持
方便集成各种优秀的框架
Spring不排斥各种优秀的开源框架,其内部提供了对各种优秀框架【h/s/m】的直接支持
降低了javaEEAPI的使用难度
Spring对javaEE开发中的API做了包装。
Spring的入门程序
1.下载spring的开发包
spring-framework-3.2.0.RELEASE-dist ----spring的开发包
*docs spring框架的API和规范
*libs spring 开发的jar包
*schema xml的约束文档【dtd】
spring-framework-3.0.2.RELEASE-dependencies --spring的开发依赖包
2.导入开发常用的基础jar包
创建java项目引入对应的jar包
spring-beans-3.2.0.RELEASE.jar
spring-context-3.2.0.RELEASE.jar
spring-core-3.2.0.RELEASE.jar
spring-expression-3.2.0.RELEASE.jar
spring-framework-3.0.2.RELEASE-dependencies\org.apache.commons\com.springsource.org.apache.commons.logging\1.1.1\com.springsource.org.apache.commons.logging-1.1.1.jar
spring-framework-3.0.2.RELEASE-dependencies\org.apache.log4j\com.springsource.org.apache.log4j\1.2.15\com.springsource.org.apache.log4j-1.2.15.jar
3.创建spring的配置文件
1.在资源目录下创建一个applicationContext.xml
2.引入xml的约束【DTD头】
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd">
//我们在这个写东西
</beans>
3.配置类
如:<beanid="ub" class="biz.UserBiz"></bean>
4.创建测试类
1.解析配置文件
ApplicationContext 工厂类 专门解析配置文件的
2.由spring给我们创建对象
3.我们得到对象后直接可以访问对象中的方法
Ioc和DI的区别?
Ioc:控制反转:将对象的创建权 由spring管理。
DI:依赖注入:在spring创建对象的过程中,把对象依赖的属性注入到类中。
*面向对象中对象之间的关系
*依赖
Public class A{
Public B b;
b.add();
}
*继承 is a
*聚合
聚集:类和类的关系紧密 如头和身体
组合:类与类的关系比较松散 如:电视机和遥控器
我们必须给创建对象的类中 需要注入值的 属性提供set方法
在bean节点中 添加节点
<propertyname="name" value="刘升东"></property> 对于普通属性的注入
<propertyname="ub" ref="ub"></property> 对于对象属性的注入
Ref=一个bean的id
Spring框架加载配置文件
ApplicationContext 应用上下文 加载spring框架配置文件
加载classPath:
newClassPathXmlApplicationContext("applicationContext.xml");
加载classpath下面配置的文件
加载磁盘路径
newFileSystemXmlApplicationContext("E:\\spring\\spring-day01-1\\property\\applicationContext.xml");
加载对应磁盘路径下的配置文件
BeanFactory与ApplicationContext区别?
ApplicationContext类继承BeanFactory
BeanFactory在使用的时候 用到getBean(“id”)的时候才会加载这个类!
ApplicationContext类加载配置文件的时候会创建所有的配置好的类【bean】
ApplicationContext对BeanFactory提供了扩展
*事件的传递
*Bean自动装配
*各种不同应用层Context的实现
------早期开发使用BeanFactory
Ioc装配Bean
Spring框架实例化Bean的方式
提供了三种方式:
1.构造方法实例化:(最常用的 默认的 使用的是无参构造)
2.静态工厂实例化
3.实例化工厂实例化
Bean的其他配置
Id和name的区别
Id遵守xml的约束,这个约束保证这个属性的值是惟一的。而且必须以字母开头
可以使用字母,数字,连字符,下划线,句号
Name没有这一些要求
…….如果bean标签上没有配置id ,那么name作为id
…….name是出现在早期开发中的
…….现在的开发都使用id属性即可
Bean的作用范围
Scope属性
*singleton 单例的(默认值)
*prototype 多例的
*request
Web开发中创建一个对象,将这个对象存入request域中 request.setAttributer()
*session
Web开发中创建一个对象,将这个对象存入session域中sesssion.setAttributer()
Bean的生命周期
配置Bean的初始化和销毁的方法
配置初始化销毁的方法在《bean节点中指定的属性》
Init-method=”对应的方法名” //对象创建的时候调用
Destory-method=”对应的方法名” //关闭工厂的时候销毁 close方法
Bean的生命周期的11个步骤:
1.instantiate bean对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware执行 setBeanName
4.如果Bean实现BeanFactoryAware或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean),执行postProcessBeforeInitialization
6.如果Bean实现InitializingBean执行 afterPropertiesSet
7.调用<beaninit-method="init"> 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(处理Bean),执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现DisposableBean 执行 destroy
11.调用<bean destroy-method="customerDestroy">指定销毁方法 customerDestroy
Bean属性的注入
Spring支持setter方法注入/支持构造的注入
构造器注入:
<beanid="ua" class="web.action.UserAction" >
<!-- 构造器注入 更具属性名
<constructor-argname="name" value="刘升东" />
<constructor-arg name="ub" ref="ub2"/>
-->
构造器注入 更具形参的下标
<constructor-arg index="0"type="java.lang.String" value="流水线" />
<constructor-arg index="1"ref="ub2"></constructor-arg>
</bean>
Setter方法的注入:[用的做多的]
<bean id="ua"class="web.action.UserAction" >
普通属性的注入
<property name="name"value="刘升东"></property>
对象属性的注入 ref 是一个 Bean的id
<property name="ub"ref="ub2"></property>
</bean>
名称空间P:属性注入
Spring2.5版本之后引入的
导入P标签的名称空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
普通属性的注入
P:属性名=“lsd” 注入常量
对象属性的注入
P:属性名-ref=”id” 注入Bean对象
如:<bean id="ua" class="web.action.UserAction" p:name="刘升东" p:ub-ref="ub2"></bean>
分割配置文件;【一旦声明的实例过多了 查找修改起来比较麻烦 找半天找不到】
一种写法:ApplicationContext ac=new ClassPathXmlApplicationContext("acDao.xml","acBz.xml");
第二种写法:
在一个主配置中引入其他的配置
<import resource="applicationContextdao.xml"/>
解析的时候只需要解析主配置就可以了
ApplicationContext ac=newClassPathXmlApplicationContext("applicationContext.xml");
IOC装配Bean(注解方式) 不需要提供set方法
Spring2.5引用了注解去定义Bean
@Component 用来描述spring框架中的bean
Spring的框架提供了与@Component注解等效的三个注解
@Repository 用于对dao实现类进行标注
@Service 用于对service实现类进行标注
@Controller 用于对Controller 实现类进行标注
-------------三个注解为了后续版本进行增加的!
Bean属性的注入
普通属性
@Value
如:@Value("动")
private String name;
对象属性
@Autowired
@Qualifier("ubi2")
如:@Autowired
@Qualifier("ubi2") //ubi2 就是Bean id
private UserBiz ub=null;
@Autowired
@Qualifier("ubi2")
等价于
@Resource(name=”ubi2”)
Bean其他属性的配置:
配置初始化方法/销毁方法
@PostConstruct 初始化
@PreDestroy 销毁
配置Bean的作用范围
@Scope("prototype") //写在 @Component的下面
实际开发中使用XML还是注解?
Xml:
*bean 管理比较方便
注解:
*注入属性的时候比较方便
两种方式合二为一:
一般使用xml注册Bean 使用注解来进行属性的注入
AOP的概述
什么是AOP
AOP为Aspect OrientedProgramming的缩写,意为:面向切面编程
AOP采取横向抽取机制,取代了传统的纵向继承体系实现代码的复用
SpringAOP是才有纯java 的是实现,不需要通过专门的编译过程和类加载器。
在运行期通过代理方式向目标对象织入增强
AspectJ 是基于java语言的AOP框架,在spring2.0提供了一套专门的编译器。
AOP思想
Spring的AOP代理:
JDK动态代理:对实现了接口的类生成代理 创建快执行慢
Cglib代理:对类生成的二进制文件的代理 创建慢执行块
<aop:configproxy-target-class="false"> false默认的JDK代理 trueCGlib代理
AOP的术语:
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点.
Pointcut(切入点):所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Introduction(引介):引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.
Target(目标对象):代理的目标对象
Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程.
spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
Aspect(切面): 是切入点和通知(引介)的结合
Spring的AOP【原始的一套面向切面编程入门程序 给业务方法做增强(添加写日志功能)】
1.在注入完成的情况下
2.引入AOP的jar包
3.使用一套AOP原始的增强接口 【实现自己的增强功能】
前置增强
//前置增强 public class Before implements MethodBeforeAdvice { private Logger logger=Logger.getLogger(Before.class);
@Override //方法对象 参数列表 类型 public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable { logger.info("方法开始执行-------------------------"); System.out.println("类型为--------"+arg2); System.out.println("方法名为--------"+arg0.getName()); System.out.println("方法的第一个参数--------"+arg1[0]); } } |
后置增强
//后置增强 public class AfterReturning implements AfterReturningAdvice { private Logger logger=Logger.getLogger(AfterReturning.class); @Override public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable { logger.info("方法执行完毕-----------------------------"); System.out.println("方法的返回值为--------"+arg0); System.out.println("类型为--------"+arg3); System.out.println("方法名为--------"+arg1.getName()); System.out.println("方法的第一个参数--------"+arg2[0]); } } |
环绕增强
//环绕增强 public class Around implements MethodInterceptor { private Logger logger=Logger.getLogger(Around.class); @Override public Object invoke(MethodInvocation arg0) throws Throwable { logger.info("环绕增强执行----------------------"); System.out.println("类型为--------"+arg0.getThis()); System.out.println("方法名为--------"+arg0.getMethod().getName()); System.out.println("方法的第一个参数--------"+arg0.getArguments()[0]); //放出 return arg0.proceed(); } } |
异常增强
//异常增强 自定义增强方法 public class AfterThrowing implements ThrowsAdvice { private Logger logger=Logger.getLogger(AfterThrowing.class); //自定义对应异常类型的增强 public void afterThrowing(Method arg1, Object[] arg2, Object arg3,Exception e) throws Throwable { logger.info("开始异常增强-------------------------"); System.out.println("异常类型为--------------"+e); } } |
4.配置AOP增强
<!-- 前置增强的实例 --> <bean id="before" class="common.Before"></bean> <!-- 后置增强的实例 --> <bean id="afterreturning" class="common.AfterReturning"></bean> <!-- 环绕增强的实例 --> <bean id="around" class="common.Around"></bean> <!-- 异常增强的实例 --> <bean id="afterThrowing" class="common.AfterThrowing"></bean>
<!-- aop的配置 --> <aop:config> <!-- 配置切点 切点表达式 --> <aop:pointcut expression="execution(* biz..add*(..))" id="pointcut"/> <!-- 织入 --> <aop:advisor advice-ref="before" pointcut-ref="pointcut" /> <!-- 织入 --> <aop:advisor advice-ref="afterreturning" pointcut-ref="pointcut"/> <!-- 织入 --> <aop:advisor advice-ref="around" pointcut-ref="pointcut"/> <!-- 织入 --> <aop:advisor advice-ref="afterThrowing" pointcut-ref="pointcut"/> </aop:config> |
execution()是最常用的切点函数,其语法如下所示:
整个表达式可以分为五个部分
如:* biz..*(..)
1、execution(): 表达式主体。
2、第一个*号:表示返回类型, *号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包
4、*(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数
Spring AspectJ的AOP *****
是2.0之后的新版 而且spring对他提供了注解技术
1.在注入完成的情况下
2.引入AOP的jar包
3.自定义增强类
//增强类 public class Loggers { private Logger logger=Logger.getLogger(Loggers.class);
//前置增强 public void before(JoinPoint jp){ logger.info("方法开始执行--------------------------------"); System.out.println("类型为------"+jp.getTarget()); System.out.println("方法名为-------"+jp.getSignature().getName()); System.out.println("第一个参数为------"+jp.getArgs()[0]); }
//后置增强 public void afterReturning(JoinPoint jp,Object obj){ logger.info("方法执行结束--------------------------------"); System.out.println("类型为------"+jp.getTarget()); System.out.println("方法名为-------"+jp.getSignature().getName()); System.out.println("第一个参数为------"+jp.getArgs()[0]); System.out.println("返回值类型是---------"+obj); }
//环绕增强 public Object around(ProceedingJoinPoint pjp) throws Throwable{ logger.info("方法开始环绕--------------------------------"); System.out.println("类型为------"+pjp.getTarget()); System.out.println("方法名为-------"+pjp.getSignature().getName()); System.out.println("第一个参数为------"+pjp.getArgs()[0]); //抛出 return pjp.proceed(); }
//异常增强 public void afterThrowing(JoinPoint jp,Exception e){ logger.info("方法出现异常--------------------------------"); System.out.println("类型为------"+jp.getTarget()); System.out.println("方法名为-------"+jp.getSignature().getName()); System.out.println("第一个参数为------"+jp.getArgs()[0]); System.out.println("异常信息是---------"+e); } //最终增强 相当于 finally public void after(JoinPoint jp){ logger.info("方法最终执行--------------------------------"); System.out.println("类型为------"+jp.getTarget()); System.out.println("方法名为-------"+jp.getSignature().getName()); System.out.println("第一个参数为------"+jp.getArgs()[0]); } } |
4编写xml配置文件
!-- 实例化增强的类 --> <bean id="log" class="common.Loggers"></bean> <!-- aop的配置 --> <aop:config> <!-- 切点 --> <aop:pointcut expression="execution(* biz..*(..))" id="pointcut"/> <!-- 织入 --> <aop:aspect ref="log"> <!-- 这就是前置增强 --> <aop:before method="before" pointcut-ref="pointcut"/> <!-- 这就是后置增强 --> <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="obj"/> <!-- 这就是环绕增强 --> <aop:around method="around" pointcut-ref="pointcut"/> <!-- 这就是异常增强 --> <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/> <!-- 这就是最终增强 --> <aop:after method="after" pointcut-ref="pointcut" />
</aop:aspect> </aop:config> |
Advisor和Aspect
Aspect可以指定多个方法的切入
现在的开发中 我们一般使用Aspect
AspactJ注解的配置
@Aspect 指明这是一个增强类
@Before前置增强
@Afterreturning 后置增强
@Around 环绕增强
@AfterThrowing 异常增强
@After 最终增强
Xml 中进行注解配置的交代
<beanclass="common.Loggers"></bean>
<!--自动生成代理类 aop:cfg -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
Spring的JDBCTemplate
JDBCTemplate模板与dbutils比较类似
Spring对持久层技术的支持
JDBC:org.springframework.jdbc.core.JdbcTemplate
Hibernate3.0:org.springframework.orm.hibernate3.HibernateTemplate
Mybatis :org.springframework.orm.ibatis.sqlMapClientTemplate
JPA :org.springframework.orm.jpa.JpaTemplate
开发JDBCTemplate入门
第一步引入jar包
*spring-tx-3.2.0.RELEASE.jar
*spring-jdbc-3.2.0.RELEASE.jar
*数据库的驱动ojdbc6.jar 我现在演示用的oracle ojdbc6.jar
第二步创建applicationContext.xml文件
第三歩 编写 测试类
Spring默认的数据源
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="DriverClassName" value="oracle.jdbc.OracleDriver" /> <property name="Url" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="Username" value="laowang"/> <property name="Password" value="niit"/> </bean> |
DBCP数据源
导入jar包:com.springsource.org.apache.commons.dbcp-1.2.2.osgi.jar
com.springsource.org.apache.commons.pool-1.5.3.jar
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="oracle.jdbc.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="username" value="laowang"/> <property name="password" value="iit"/> </bean> |
C3p0连接池
导入jar包com.springsource.com.mchange.v2.c3p0-0.9.1.2.jar
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="oracle.jdbc.OracleDriver" /> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:ORCL"/> <property name="user" value="laowang"/> <property name="password" value="iit"/> </bean> |
参数放在对应的配置文件中 引用到spring配置文件中
第一种
<!-- spring提供 解析jdbc.properties的类 -->
<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location"value="classpath:jdbc.properties"></property>
</bean>
第二种
<context:property-placeholderlocation="classpath:jdbc.properties"/>
什么引用:如:value="${jdbc.driver}"
JDBCTemplate的CRUD操作
Spring框架中提供了对持久层的支持类
Jdbc:org.springframework.jdbc.core.support.JdbcDaoSupport
编写Dao的时候
注入:JdbcTemplatejdbcTemplate 类
进行CRUD操作
保存 update(String sql,Object ….args);
修改 update(String sql,Object ….args);
删除 update(String sql,Object ….args);
查询
简单查询
Selectcount(*) from user --queryForInt(String sql)
Selectname from user where id=1 --queryForObject(Stringsql)
复杂查询
返回对象 .queryForObject(sql, rowMapper, args)
返回集合 query(sql, owMapper);
内部类【把我们的result数据封装成想要的对象】
//编写内部类 class UserRowMapper implements RowMapper<User>{ /* * rs结果集 * rowNum 行号 */ @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { // TODO Auto-generated method stub User user=new User(); user.setId(rs.getInt(1)); user.setName(rs.getString(2)); user.setPwd(rs.getString(3)); return user; } } |
Spring的事务管理
什么是事务管理?
事务:逻辑上的一组操作,要么都成功 要么都失败
事务的特性
ACID
原子性:事务不可分割 【要么都成功 要么都失败】
一致性:事务执行前后,数据完整性保持一致【更新之后 数据的和不变】
隔离性:一个事务执行的时候,不应该受其他事务的影响。
持久性:事务一旦结束,数据就将永久的保存在 数据库
如果不考虑隔离性:
脏读:一个事务读到另一个事务未提交的数据
【刘升东转钱给张清元 张清元查看余额】
不可重复读:一个事务读到另一个事务已提交的数据
【update 导致一个事务多次查询的结果不一致】
虚读:一个事务读到另一个事务已提交的数据
【insert 导致一个事务多次查询的结果不一致】
事务的隔离级别
未提交读:以上情况都有可能发生【读的对快的 但是出现脏数据的可能性 最高的】
已提交读:避免脏读,但不可重复读,虚读是有可能发生的
可重复读:避免脏读,不可重复读,虚读可能发生
串行读 :避免以上所有的情况 【读的最精准的 但是最慢的】
Spring中的事务管理
分层开发:事务处在biz【业务 service】层
Spring提供的事务管理的API
PlatformTransactionManager: 平台事务管理器
TransactionStatusgetTransaction(TransactionDefinitiondefinition) //获得事务
void commit(TransactionStatus status) //提交事务
void rollback(TransactionStatus status) //回滚事务
TransactionDefinintion:事务的定义
ISOLATION_****:定义事务的隔离级别
PROPAGATION_****:定义事物的传播机制
TransactionStatus:事务的状态
hasSavepoint()是否有保存点
isNewTransaction()是否是一个新的事务
isRollbackOnly() 事务是否以提交
三者的关系:PlatformTransactionManager通过TransactionDefinintion设置事务相关的信息,管理事务的过程中,产生的一些事务的状态由TransactionStatus来记录
API的详解
PlatformTransactionManager
Spring为了不同的持久化框架提供了不同的实现类
SpringJDBC或ibatis进行持久化时使用:
org.springframework.jdbc.datasource.DataSourceTransactionManager
hibernate3.0版本进行持久化时使用:
org.springframework.orm.hibernate3.HibernateTransactionManager
JPA进行持久化时使用:
org.springframework.orm.jpa.JpaTransactionManager
TransactionDefinintion:事务的定义接口
Spring为事务的隔离级别/传播行声明了不同的常量表示
【隔离常量】
ISOLATION_DEFAULT :使用后端数据库默认的隔离级别【spring中的选项】
ISOLATION_READ_COMMITTED 【oracle数据库默认的隔离级别 允许在并发事务提交后读取,可防止脏读,但是幻读和不可重复读任肯发生】
ISOLATION_REPEATABLE_READ 【mysql 对于相同只读多次读取是一致的,除非数据被事务本身修改,可防止脏读,不可重复读,但是幻读可能发生】
ISOLATION_READ_UNCOMMITTED 【允许你读取 还未提交的改变的数据 ,可能出现脏,幻,不可重复读】
ISOLATION_SERIALIZABLE 【完全服从ACID的隔离级别 确保不发生 脏读/幻读/不可重复读。】
【传播机制的常量】
PROPAGATION_REQUIRED 支持当前事物,如果不存在 新建一个事务
【A,B 如果A有事务,B就使用A的事务,,如果A没有事物,B就开启一个新的事务
(A,B在同一个事务中)】
PROPAGATION_SUPPORTS 支持当前的事务,如果不存在,就不使用事务
【A,B 如果A有事务 B使用A的事务, 如果A没有事务 B就不使用事物】
PROPAGATION_MANDATORY 支持当前事务;如果没有当前事务,则抛出异常。
【A,B 如果A有事务 B就使用A的事务 如果A没有事务 抛出异常】
PROPAGATION_REQUIRES_NEW 如果有事务存在挂起当前事务 创建新的事务
【A,B 如果A有事务 B将A的事务挂起 重新创建新的事务
(A,B不在同一事务)】
PROPAGATION_NOT_SUPPORTED 如果存在事务挂起当前事务
【A,B 非事务的运行方式 A有事务 直接挂起当前的事务】
PROPAGATION_NEVER 不支持当前事务;如果当前事务存在,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务 则嵌套事务执行
【基于:savePoint技术 保存点
A,B A有事务,A执行后,将A事务执行后的内容保存到SavePoint,如果B事物有异常的话,用户需要手动的设置事物是回滚还是提交。
】
常用的【***】
PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
Spring的事务管理:
Spring的事物管理分为2类
1.编程式事务管理 【手动编程 敲代码完成事务管理】
2.声明式事务管理 【不需要手动敲 配置即可】
使用spring的事物模拟银行转账功能
1.导入相应的jar包
2.配置 配置文件
ApplicationContext.xml log4j.properties jdbc.properties
3.创建对应的接口和实现类
Dao/biz
4.spring的事务管理
手动编码完成事务的管理
需要事务的管理器:真正管理事务的对象【commit/rollback….】
Spring 还提供了事物管理的模板【工具类对事务的管理器的封装】
1.注册事务的管理器
<beanid="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"></bean> |
2.注册事务的模板
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" p:transactionManager-ref="transactionManager"></bean> |
3.把模板注入给biz
<bean id="userBiz" class="biz.UserBizImp" p:ud-ref="userDao" p:tt-ref="transactionTemplate"></bean> |
4.biz更具模板开启事物/提交事物/回滚事务
tt.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus arg0) {
ud.outMoney(outName, money); int i=1/0; ud.inMoney(inName, money); } |
缺点:代码量的增加 代码有侵入性 每一个业务先要用事物必须来一套
声明式事务管理:【基于切面的 自动代理 ***】
1.导入相应的jar包
2.配置配置文件
ApplicationContext.xml log4j.properties jdbc.properties
3.创建对应的接口和实现类
Dao/biz
4.spring配置 增强/代理
1.注册管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"></bean> |
2.定义增强类【事务管理】
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <!-- 增强事务的属性配置 --> <tx:attributes> <!-- 指定增强的方法 isolation 事物额隔离级别 propagation 事物的传播机制 read-only false为只读 no-rollback-for 发生哪些异常不回滚 rollback-for 发生哪些异常回滚 --> <tx:method name="transfer*" /> </tx:attributes> </tx:advice> |
3.定义aop的配置
<aop:config> <!-- 定义切点 --> <aop:pointcut expression="execution(* biz..*(..))" id="pointcut"/> <!-- 织入 --> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut" /> </aop:config> |