spring
@(JAVAWEB)
介绍(基于spring 4.2.4)
对象的容器,spring负责管理项目中的所有对象,可以看成是整个项目的管家
spring是一站式的框架
正因为是容器,容器中装了狠多对象比如web操作的对象,service的对象,dao的对象
spring搭建
- 1.导包
这几个包,是spring的核心包(core)
导包之后并没有完成需要 创建xml文件
一般命名为applicationContext.xml
然后需要添加xml约束
接下来是将类放入Spring的容器中
-新建User类
@Component("user")
//相当于xml文件中的an配置
//最好用下面几种方式
//@Service("user")
//@Controller("user")
//@Repository("user")
//@Scope(scopeName = "prototy")//此属性来设置user类是否是单例还是多例默认单例。
public class User {
@Value("vv")//也可以添加到set方法上,在属性上面是通过反射的field进行赋值,而方法上是通过set方法赋值
private String name;
private int age;
@Autowired //自动装配,前提是car类需要进行component等注解。
//Autowired会有一问题当spring容器中有多个car类型的对象时,如car1,car2时可以使用下面两种注解
//@Qualifier("car2") 不推荐此种需要和Autowired一起配合使用
//@Resource(name = "car2")建议这种方式,当容器中有多个引用对象的时候
private Car car;
public User() {
System.out.println("空参构造");
}
public Car getCar() {
return car;
}
public void setCar(Car car) {
this.car = car;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", car=" + car +
'}';
}
@PostConstruct //在对象创建之后调用等同于 init-method
public void init() {
System.out.println("我是初始化方法");
}
@PreDestroy //在销毁前调用
public void destroy() {
System.out.println("我是销毁方法");
}
}
2.到applicationContext.xml中配置
IDEA会自己生成Spring得约束XML文件
代码测试
测试结果
spring概念
IOC (Inverse Of Control) 概念:
将我们创建对象的方式反转,一千对象的创建由我们开发人员自己维护,包括依赖关系也是自己注入.
使用了Spring之后,对象的创建和依赖关系可以由Spring完成创建以及注入.
简单来说就是:反转了对象的创建方式,有自己创建变为了程序控制.
DI(dependency Injection):实现IOC思想需要DI支持
注入方式:
- 1.set方式
- 2.构造方法注入
- 3.字段注入
注入类型:
- 值类型注入:基本数据类型
- 引用类型注入:将依赖对象注入
applicationContext和anfactory
BeanFactory
Spring原始接口的实现类功能单一
anFactory接口实现类的容器,特点是每次在获得对象时才会创建对象。
applicationContext
特点:每次容器启动时就会创建容器中配置的所有对象。
提供了更多功能。
从类路劲下加载配置文件:classPathXMLApplicationContext
从硬盘绝对路劲下加载配置文件FilePathXMLApplicationContext
web开发中使用applicationContext,在资源匮乏的环境可以使用anFactory。
spring配置详解
Bean元素
Spring创建对象方式
1.空参构造方式
静态工厂方式
动态工厂方式
an元素晋级
scope属性
singleton(默认)单例对像,spring容器中只会存在一个实例
prototype(多例):每次获得时都会创建对象。和struts2使用时必须配置为多例。
request:web环境下对象鱼request对象生命周期一样
session:web环境下雨session声明周期一致
生命周期属性:配置一个方法作为声明周期初始化方法。spring会在对象创建之后首先调用
配置一个而方法作为生命周期的销毁方法,spring会在结束前调用该方法。
spring的分模块化配置
Spring属性注入:set方法
在user中添加car属性
加上car对象
两个都要重写toStirng方法
目录结构
xml中配置
测试代码
测试结果
构造函数注入
或者
p名称空间注入
spel注入
复杂类型注入(了解)
用注解配置xml
在原来的lib上添加
步骤
1.为主配置文件引入新的命名空间(约束)
通添加xml约束一样。
2.开启注解配置文件
3.在类中使用注解。
1)类注解
2)值注入
3)引用类型注入
4)初始化、销毁注入
spring与junit整合
首先导包
spring中的AOP
思想:横向重复,纵向抽取。
对目标对象中的方法进行增强.
具体还清楚
spring中的aop原理
动态代理(优先)
被代理的对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理及技术
cglib
第三方代理技术,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理,如果目标对象呗final修饰,那么该类无法被cglib代理。
aop名词
joinpoint(连接点):目表对象中,所有增强的方法。
pointcut(切入点):目标对象中,已经增强的方法。
advice(通知/增强):增强的代码。
Target(目标对象):被代理对象,代码中的UserSevviceImpl
Weaving(织入):将通知应用到切入的点的过程
Proxy:将通知织入大目标对象后,形成代理对象。
aspect(切面):切入点+通知。
Spring中的aop演示
1.导包4+2+2+2:
2.准备目标对象
/**
* Created by Bove_shu on 2017/6/9.
*/
public class UserServiceImp implements UserService {
@Override
public void save() {
System.out.println("保存用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("更新用户");
}
@Override
public void find() {
System.out.println("查找用户");
}
}
3.准备通知
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 通知类
* Created by Bove_shu on 2017/6/9.
*/
public class MyAdvice {
//前置通知
// |-目标方法运行之前调用
//后置通知(如果出现异常不会调用)
// |-在目标方法运行之后调用
//环绕通知
// |-在目标方法之前之后都调用
//异常拦截通知
// |-如果出现异常,就会调用
//后置通知
// |-目标方法调用之后
//前置通知
public void fore() {
System.out.println("这是前置通知");
}
//后置通知
public void afterReturning() {
System.out.println("这是后置通知(如果出现异常不会调用)");
}
//环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("这是环绕前置通知");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("这是环绕后置通知(如果出现异常不会调用)");
return proceed;
}
//异常通知
public void afterException() {
System.out.println("出事啦!");
}
//后置通知
public void after() {
System.out.println("这是后置通知出现异常也会调用");
}
}
4.配置进行织入,将通知织入目标对象。
Spring中的Aop配置(xml配置)
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!--aop配置主要是上面两行-->
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--//目标配置对象-->
<an name="userServiceTarget" class="Service.UserServiceImp"></an>
<!--配置通知对象-->
<an name="myAdvice" class="Aspect.MyAdvice"></an>
<!--配置将通知织入目标对象-->
<aop:config>
<!--配置切入点-->
<!--
void Service.UserServiceImp.save() 表示对修饰符不受限制
* Service.UserServiceImp.save() 标识对修饰符和返回值不做限制
* Service.UserServiceImp.*() 表示对UserServiceImp类下所有的空参方法进行增强.
* Service.UserServiceImp.*(..) 表示对UserServiceImp类下所有的方法进行增强.
* Service.*ServiceImp.*(..) 表示从service包下找以ServiceImp的所有类.
* Service..*ServiceImp.*(..)表示从service包下找以ServiceImp的所有类(包括子包)
-->
<aop:pointcut id="pc" expression="execution(* Service..*ServiceImp.*(..))"/>
<aop:aspect ref="myAdvice">
<aop:fore method="fore" pointcut-ref="pc"/>
<aop:after-returning method="afterReturning" pointcut-ref="pc"/>
<aop:around method="around" pointcut-ref="pc"/>
<!--异常-->
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<aop:after method="after" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
</ans>
Spring中的Aop配置(注解配置)
前两步步和上面一样
- 准备通知对象
/**
* 通知类
* Created by Bove_shu on 2017/6/9.
*/
@Aspect
//标识该类是通知类
public class MyAdvice {
//前置通知
// |-目标方法运行之前调用
//后置通知(如果出现异常不会调用)
// |-在目标方法运行之后调用
//环绕通知
// |-在目标方法之前之后都调用
//异常拦截通知
// |-如果出现异常,就会调用
//后置通知
// |-目标方法调用之后
@Pointcut("execution(* Service..*ServiceImp.*(..))")
public void pc(){
}
//前置通知
@fore("MyAdvice.pc())")
public void fore() {
System.out.println("这是前置通知");
}
//后置通知
@AfterReturning("MyAdvice.pc())")
public void afterReturning() {
System.out.println("这是后置通知(如果出现异常不会调用)");
}
//环绕通知
@Around("MyAdvice.pc())")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("这是环绕前置通知");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("这是环绕后置通知(如果出现异常不会调用)");
return proceed;
}
//异常通知
@AfterThrowing("MyAdvice.pc())")
public void afterException() {
System.out.println("出事啦!");
}
//后置通知
@After("MyAdvice.pc())")
public void after() {
System.out.println("这是后置通知出现异常也会调用");
}
}
- 将通知织入目标对象
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<!--aop配置主要是上面两行-->
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--//目标配置对象-->
<an name="userServiceTarget" class="Service.UserServiceImp"></an>
<!--配置通知对象-->
<an name="myAdvice" class="AnnotationAspect.MyAdvice"></an>
<!--开启注解完成织入-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</ans>
Spring整合JDBC
spring中提供了一个可以操作数据库的对象,对象封装了JDBC技术.
JDBCTemplate JDBC模板
- 准备工作(4+2)
- Spring-test包+spring-aop包 jdbc驱动 连接池c3p0 spring-jdbc spring-tx(事务)
- jdbc驱动 连接池c3p0
代码(没用用spring配置的代码):
- 需要一个springJDBC模板(该类是接口)定义该类的方法
/**
* Created by Bove_shu on 2017/6/11.
*/
public interface UserDao {
//增
void save(TUser user);
// 删
void update(TUser user);
// 改
void delete(int id);
TUser getById(int id);
// 查
int getTotalCount();
//查
List<TUser> getAll();
}
2.模板的实现类.具体些数据库操作.
/**
* Created by Bove_shu on 2017/6/11.
*/
public class UserDaoImpl implements UserDao {
private JdbcTemplate jt;
public JdbcTemplate getJt() {
return jt;
}
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
@Override
public void save(TUser user) {
String sql = "insert into t_user values(null,?)";
jt.update(sql, user.getName());
}
@Override
public void update(TUser user) {
String sql = "UPDATE t_user SET NAME =? WHERE id=?";
jt.update(sql, user.getName(), user.getId());
}
@Override
public void delete(int id) {
String sql = "delete from t_user where id=?";
jt.update(sql, id);
}
@Override
public TUser getById(int id) {
String sql = "SELECT * from t_user where id=?";
//这里使用new RowMapper来进行查找 第一个参数resultSet是查询结果的集合,从set中抽取结果放入TUser类中
// 第二个参数是方法调用了几次,就是几.
jt.queryForObject(sql, (resultSet, i) -> {
TUser u = new TUser();
u.setId(resultSet.getInt("id"));
u.setName(resultSet.getString("name"));
return u;
}, id);
return null;
}
@Override
public int getTotalCount() {
String sql = "SELECT count(*) from t_user where id=?";
// 返回个数就用下面的这行代码
Integer count = jt.queryForObject(sql, Integer.class);
return count;
}
@Override
public List<TUser> getAll() {
String sql = "SELECT * from t_user ";
//放回集合是下面的代码,这不需要list.add的方法,你只需要做对Tuser的赋值即可.
List<TUser> list = jt.query(sql, new RowMapper<TUser>() {
@Override
public TUser mapRow(ResultSet resultSet, int i) throws SQLException {
TUser u = new TUser();
u.setId(resultSet.getInt("id"));
u.setName(resultSet.getString("name"));
return u;
}
});
return list;
}
}
- 测试代码
@Test
public void test() throws PropertyVetoException {
//准备连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc,Driver");
dataSource.setJdbcUrl("jdbc:mysql:///spring-jdbc");
dataSource.setUser("root");
dataSource.setPassword("root");
//1 创建JDBC模板对象
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
//2书写sql执行
String sql="insert into t_user values(null,'vv')";
jt.update(sql);
}
使用spring配置写代码
- 首先要将用到的类放到容器中,从最底层的开始放入容器中(那个类是最底层可以参考上面的测试代码)
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--将连接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<!--将JDbcTemplate放入容器-->
<an name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</an>
<!--将userDao放入容器-->
<an name="userDao" class="SpringJDBC.UserDaoImpl">
<property name="jt" ref="jdbcTemplate"/>
</an>
</ans>
dao的实现类不变(模板的实现类不变)
使用sping测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class jdbcTest {
@Autowired
UserDao userDao;
@Test
public void test() throws PropertyVetoException {
//准备连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc,Driver");
dataSource.setJdbcUrl("jdbc:mysql:///spring-jdbc");
dataSource.setUser("root");
dataSource.setPassword("root");
//1 创建JDBC模板对象
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
//2书写sql执行
String sql="insert into t_user values(null,'vv')";
jt.update(sql);
}
@Test
public void save() throws PropertyVetoException {
TUser u=new TUser();
u.setName("bove");
userDao.save(u);
}
@Test
public void update() throws PropertyVetoException {
TUser u=new TUser();
u.setName("bove");
u.setId(2);
userDao.update(u);
}
}
另一种方式
继承JDBCDaoSupport
我只写了一种方式其他方法我就不完善了. 之前的jt用getJdbcTemplate()代替 ,
并且容器中也不需要再配置.
xml配置
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--将连接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<!--将JDbcTemplate放入容器-->
<!--<an name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">-->
<!--<property name="dataSource" ref="dataSource"></property>-->
<!--</an>-->
<!--将userDao放入容器-->
<an name="userDao" class="SpringJDBC.UserDao2">
<!--<property name="jt" ref="jdbcTemplate"/>-->
<property name="dataSource" ref="dataSource"/>
</an>
</ans>
代码
public class UserDao2 extends JdbcDaoSupport implements UserDao {
@Override
public void save(TUser user) {
String sql = "insert into t_user values(null,?)";
//这里
getJdbcTemplate().update(sql, user.getName());
}
@Override
public void update(TUser user) {
}
@Override
public void delete(int id) {
}
@Override
public TUser getById(int id) {
return null;
}
@Override
public int getTotalCount() {
return 0;
}
@Override
public List<TUser> getAll() {
return null;
}
}
Spring中的事务
事务:要么成功要么失败.
事务特性:acid
(原子性,一致性,持久性,隔离性)
事务的并发问题:脏读
,幻读
,不可重复读
.
事务的隔离级别:
1读未提交
2读已提交
4可重复度
8串行化
spring封装了事务管理代码
事务操作
打开事务
提交事务
回滚事务
事务操作
事务操作对象
因为在不同平台,操作事务的代码各不相同,springs提供了一个接口.
PlatformTransactionManager接口,这个接口是spring中最重要的对象
JDBCTransactionManager
HirbateTransactionManager
spring管理事务的属性介绍
事务的隔离级别
是否只读
事务的传播行为
事务传播行为
spring管理事务的方式
编码式(不推荐)
1.蒋核心事务管理器配置到容器中
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--事务核心管理器,封装了所有事务操作,依赖于连接池.-->
<an name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</an>
<!--事务模板-->
<an name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</an>
<!--将连接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<an name="accountDao" class="tx.Dao.AccountDaoimpl">
<property name="dataSource" ref="dataSource"/>
</an>
<an name="accountService" class="tx.Service.AccountServiceImpl">
<property name="dao" ref="accountDao"/>
<property name="tt" ref="transactionTemplate"/>
</an>
</ans>
2.代码中使用
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate tt;
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
public AccountDao getDao() {
return dao;
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
@Override
public void transfer(int from, int to, double money) {
tt.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//捡钱
dao.decreaseMoney(from, money);
//加钱
dao.increaseMoney(to, money);
}
});
}
}
aopxml配置
准备工作导包
导入新的约束
配置通知
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--事务核心管理器,封装了所有事务操作,依赖于连接池.-->
<an name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</an>
<!--事务模板-->
<an name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</an>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--name->代表方法名-->
<!--isolation->代表隔离级别-->
<!--propagation->传播行为-->
<!--read-only->是否只读-->
<tx:method name="transfer" isolation="DEFAULT" propagation="REQUIRED" read-only="false"/>
</tx:attributes>
</tx:advice>
<!--将通知织入目标对象-->
<aop:config>
<aop:pointcut id="txPc" expression="execution(* tx.Service.*AccountServiceImpl.*(..))"></aop:pointcut>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPc"/>
</aop:config>
<!--将连接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<an name="accountDao" class="tx.Dao.AccountDaoimpl">
<property name="dataSource" ref="dataSource"/>
</an>
<an name="accountService" class="tx.Service.AccountServiceImpl">
<property name="dao" ref="accountDao"/>
<property name="tt" ref="transactionTemplate"/>
</an>
</ans>
当需要开启事务的方法有很多的时候,可以用下面的方法进行
*表示通配符
注解配置
准备工作导包
导入新的约束
开启注解管理事务
首先需要到xml中配置
<?xml version="1.0" encoding="UTF-8"?>
<ans xmlns="http://www.springframework.org/schema/ans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/ans
http://www.springframework.org/schema/ans/spring-ans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--指定扫描an包下的所有类中的注解,an下所有包都要扫描-->
<!--<context:component-scan base-package="an"></context:component-scan>-->
<!--事务核心管理器,封装了所有事务操作,依赖于连接池.-->
<an name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</an>
<!--事务模板-->
<an name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</an>
主要是这行
<tx:annotation-driven/>
<!--将连接池放入spring容器-->
<an name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="user" value="root"></property>
<property name="password" value="root"/>
<property name="driverClass" value="com.mysql.jdbc,Driver"/>
<property name="jdbcUrl" value="jdbc:mysql:///spring-jdbc"/>
</an>
<an name="accountDao" class="tx.Dao.AccountDaoimpl">
<property name="dataSource" ref="dataSource"/>
</an>
<an name="accountService" class="tx.Service.AccountServiceImpl">
<property name="dao" ref="accountDao"/>
<property name="tt" ref="transactionTemplate"/>
</an>
</ans>
代码层
//代表类中的所有方法都采用此事务,当个别不一样的时候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = false)
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate tt;
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
public AccountDao getDao() {
return dao;
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
// @Override
// public void transfer(int from, int to, double money) {
// tt.execute(new TransactionCallbackWithoutResult() {
// @Override
// protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// //捡钱
// dao.decreaseMoney(from, money);
// //加钱
// dao.increaseMoney(to, money);
// }
// });
//
// }
@Override
//个别不一样的时候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = true)
public void transfer(int from, int to, double money) {
//捡钱
dao.decreaseMoney(from, money);
int a=1/0;
//加钱
dao.increaseMoney(to, money);
}
}
当前的事务管理用到的类
目录结构
AccountDao类
public interface AccountDao {
//价钱
void increaseMoney(int id,Double money);
//捡钱
void decreaseMoney(int id,Double money);
}
AccountDaoimpl类
public class AccountDaoimpl extends JdbcDaoSupport implements AccountDao {
@Override
public void increaseMoney(int id, Double money) {
getJdbcTemplate().update("UPDATE t_account SET money=money+? WHERE id=?",money,id);
}
@Override
public void decreaseMoney(int id, Double money) {
getJdbcTemplate().update("UPDATE t_account SET money=money-? WHERE id=?",money,id);
}
}
AccountService类
public interface AccountService {
//转账方法
void transfer(int from,int to,double money);
}
AccountServiceImpl类
//代表类中的所有方法都采用此事务,当个别不一样的时候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = false)
public class AccountServiceImpl implements AccountService {
private AccountDao dao;
private TransactionTemplate tt;
public void setTt(TransactionTemplate tt) {
this.tt = tt;
}
public AccountDao getDao() {
return dao;
}
public void setDao(AccountDao dao) {
this.dao = dao;
}
// @Override
// public void transfer(int from, int to, double money) {
// tt.execute(new TransactionCallbackWithoutResult() {
// @Override
// protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// //捡钱
// dao.decreaseMoney(from, money);
// //加钱
// dao.increaseMoney(to, money);
// }
// });
//
// }
@Override
//个别不一样的时候在方法上面加此注解就行了
@Transactional(isolation = Isolation.REPEATABLE_READ ,propagation = Propagation.REQUIRED,readOnly = true)
public void transfer(int from, int to, double money) {
//捡钱
dao.decreaseMoney(from, money);
int a=1/0;
//加钱
dao.increaseMoney(to, money);
}
}
测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test {
@Autowired
private AccountService as;
@org.junit.Test
public void test(){
as.transfer(1,2,200);
}
}