Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架.
Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。
Spring作为SE、EE开发的一站式框架具有以下优点:
下载指定版本的Spring(我这里用的4.2.4):https://repo.spring.io/release/org/springframework/spring/
下载解压后的目录如下:
IOC控制反转将对象的创建权交给了Spring管理,而DI的前提是必须有IOC环境(Spring管理类的时候将类依赖的 属性注入)
applicationContext.xml的配置示例:
<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">
<bean id="userDao" name="userDao" class="com.itheima.spring.demo1.UserDaoImpl" init-method="setup" destroy-method="destory">
<property name="name" value="张三bean">property>
bean>
beans>
代码示例:
package com.itheima.spring.demo1;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.sun.glass.ui.Application;
import org.springframework.context.ApplicationContext;
public class SpringDemo1 {
@Test
//传统方式调用
public void demo1() {
UserDao userDao = new UserDaoImpl();
userDao.setName("张三");
userDao.save();
}
@Test
//Spring方式调用
public void demo2() {
//ApplicationContext
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
UserDao userDao = (UserDao)applicationContext.getBean("userDao");
userDao.save();
applicationContext.close();
}
}
bean标签的id和name,其中id使用了唯一约束里面不能出现特殊字符,name没有使用唯一约束里面可以出现特殊字符(例如spring和structs1整合的时候
)
scope属性
支持构造方法方式和set方法方式,但前提是类支持set方法和构造方法
<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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="car" class="com.itheima.spring.demo4.Car">
<constructor-arg name="name" value="大众">constructor-arg>
<constructor-arg name="price" value="100000">constructor-arg>
bean>
<bean id="car2" class="com.itheima.spring.demo4.Car">
<property name="name" value="宝马">property>
<property name="price" value="1000000">property>
bean>
<bean id="employee" class="com.itheima.spring.demo4.Employee">
<property name="name" value="张三">property>
<property name="car" ref="car2">property>
bean>
<bean id="car3" class="com.itheima.spring.demo4.Car" p:name="奇瑞" p:price="1000">
<bean id="employee1" class="com.itheima.spring.demo4.Employee" p:name="李四" p:car3-ref="car3">
<bean id="carInfo" class="com.itheima.spring.demo4.CarInfo">bean>
<bean id="car4" class="com.itheima.spring.demo4.Car">
<property name="name" value="#{carInfo.name}">property>
<property name="price" value="#{carInfo.calculatorPrice()}">property>
bean>
<bean id="employee4" class="com.itheima.spring.demo4.Employee">
<property name="name" value="#{'王五'}">property>
<property name="car" value="#{car4}">property>
bean>
<bean id="collectionBean" class="com.itheima.spring.demo4.CollectionBean">
<property name="arrs">
<list>
<value>aaavalue>
<value>bbbvalue>
list>
property>
<property name="list">
<list>
<value>cccvalue>
<value>dddvalue>
list>
property>
<property name="set">
<set>
<value>eeevalue>
<value>fffvalue>
set>
property>
<property name="map">
<map>
<entry key="ggg" value="111">entry>
<entry key="hhh" value="222">entry>
map>
property>
bean>
beans>
有两种方式,一种是代码加载xml,另一种是xml文件包含
可以在代码中加载多个applicationContext.xml文件,如下:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml");
也可以使用import将applicationContext2.xml包含到applicationContext.xml中,如下:
<import resource="applicationContext2.xml"/>
@Component(value=“userDao”)//相当于
@PostConstruct//相当于
@Predestroy//相当于注意工厂关闭时才执行
<?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">
<!-- Spring的IOC的注解入门 -->
<!-- 使用IOC的注解开发,需要配置组件扫描(哪些包下的类使用IOC注解) -->
<context:component-scan base-package="com.tiheima.spring.demo1"></context:component-scan>
</beans>
package com.tiheima.spring.demo1;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component(value="userDao")//相当于
public class UserDaoImpl implements UserDao {
private String name;
@Value(value="张三啊")//假如没有set方法,则将属性注解加到属性上
public void setName(String name) {
this.name = name;
}
@Override
public void save() {
System.out.println("UserDaoImpl中的save()方法执行了..."+name);
}
}
package com.tiheima.spring.demo1;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserServiceImpl implements UserService {
//注入DAO
@Autowired
@Qualifier(value="userDao")
private UserDao userDao;
@Override
public void save() {
System.out.println("UserService的save方法执行了");
userDao.save();
}
}
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
AOP通知类型有:前置、后置、环绕、异常抛出与最终通知。
ProductDaoImpl代码:
package com.itheima.spring.demo3;
public class ProductDaoImpl implements ProductDao {
@Override
public void save() {
System.out.println("save...");
}
@Override
public void update() {
System.out.println("update...");
}
@Override
public void find() {
System.out.println("find...");
int num = 1/0;
}
@Override
public String delete() {
System.out.println("delete...");
return "后置通知返回值";
}
}
MyAspectXML代码:
package com.itheima.spring.demo3;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
public class MyAspectXML {
public void checkPri(JoinPoint joinPoint) {
System.out.println("权限校验==========="+joinPoint);
}
public void writeLog(Object result) {
System.out.println("日志记录==========="+result);
}
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前通知===========");
Object obj = joinPoint.proceed();
System.out.println("环绕后通知===========");
return obj;
}
public void afterThrowing(Throwable ex) {
System.out.println("异常抛出通知==========="+ex.getMessage());
}
public void after() {
System.out.println("最终通知===========");
}
}
SpringDemo3代码:
package com.itheima.spring.demo3;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo3 {
@Resource(name="productDao")
private ProductDao productDao;
@Test
public void demo1() {
productDao.save();
productDao.update();
productDao.find();
productDao.delete();
}
}
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"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- bean definitions here -->
<!-- 配置目标对象:被增强的对象 -->
<bean id="productDao" class="com.itheima.spring.demo3.ProductDaoImpl"></bean>
<!-- 将切面类交给Spring管理 -->
<bean id="myAspect" class="com.itheima.spring.demo3.MyAspectXML"></bean>
<!-- 通过AOP的配置完成对目标类产生代理 -->
<aop:config>
<!-- 表达式配置哪些类的哪些方法需要进行增强 -->
<aop:pointcut expression="execution(* com.itheima.spring.demo3.ProductDaoImpl.save(..))" id="pointcut1"/>
<aop:pointcut expression="execution(* com.itheima.spring.demo3.ProductDaoImpl.delete(..))" id="pointcut2"/>
<aop:pointcut expression="execution(* com.itheima.spring.demo3.ProductDaoImpl.update(..))" id="pointcut3"/>
<aop:pointcut expression="execution(* com.itheima.spring.demo3.ProductDaoImpl.find(..))" id="pointcut4"/>
<!-- 配置切面 -->
<aop:aspect ref="myAspect">
<!-- 前置通知 -->
<aop:before method="checkPri" pointcut-ref="pointcut1"/>
<!-- 后置通知 -->
<aop:after-returning method="writeLog" pointcut-ref="pointcut2" returning="result"/>
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pointcut3"/>
<!-- 异常抛出通知 -->
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut4" throwing="ex"/>
<!-- 最终通知 -->
<aop:after method="after" pointcut-ref="pointcut4"/>
</aop:aspect>
</aop:config>
</beans>
OrderDao代码:
package com.itheima.spring.demo1;
public class OrderDao {
public void save() {
System.out.println("保存订单...");
}
public void update() {
System.out.println("修改订单...");
}
public String delete() {
System.out.println("删除订单...");
return "后置增强返回值";
}
public void find() {
System.out.println("查询订单...");
int sum = 1 / 0;
}
}
MyAspectAnno代码:
package com.itheima.spring.demo1;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
/**
* 切面类:注解的切面类
* @author cgs
*
*/
@Aspect
public class MyAspectAnno {
@Before(value = "execution(* com.itheima.spring.demo1.OrderDao.save(..))")
public void before() {
System.out.println("前置增强===========");
}
@AfterReturning(value="execution(* com.itheima.spring.demo1.OrderDao.delete(..))",returning="result")
public void afterReturning(Object result) {
System.out.println("后置增强==========="+result);
}
@Around(value="execution(* com.itheima.spring.demo1.OrderDao.update(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前增强===========");
Object obj = joinPoint.proceed();
System.out.println("环绕后增强===========");
return obj;
}
@AfterThrowing(value="execution(* com.itheima.spring.demo1.OrderDao.find(..))",throwing="e")
public void afterThrowing(Throwable e) {
System.out.println("异常抛出增强==========="+e.getMessage());
}
@After(value="MyAspectAnno.pointcut1()")
public void after() {
System.out.println("最终增强===========");
}
@Pointcut(value="execution(* com.itheima.spring.demo1.OrderDao.find(..))")
private void pointcut1() {}
}
SpringDemo1代码:
package com.itheima.spring.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* Spring的AOP的注解开发
* @author cgs
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringDemo1 {
@Resource(name="orderDao")
private OrderDao orderDao;
@Test
public void demo1() {
orderDao.save();
orderDao.update();
orderDao.delete();
orderDao.find();
}
}
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 在配置文件中开启注解的AOP开发 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 配置目标类 -->
<bean id="orderDao" class="com.itheima.spring.demo1.OrderDao" />
<!-- 配置切面类 -->
<bean id="myAspect" class="com.itheima.spring.demo1.MyAspectAnno" />
</beans>
JdbcDemo1代码:
package com.itheima.jdbc.demo1;
import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
/**
* JDBC模板的使用
* @author cgs
*/
public class JdbcDemo1 {
@Test
// jdbc模板的使用类似于Dbutils
public void demo1() {
// 创建连接池
DriverManagerDataSource dataSource = new DriverManagerDataSource();//spring默认内置连接池
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///spring4_day03");
dataSource.setUsername("root");
dataSource.setPassword("p@ssw0rd");
// 创建模板
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update("insert into account values(null,?,?)","cgs",10000d);
}
}
JdbcDemo2代码:
package com.itheima.jdbc.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
public void demo1() {
jdbcTemplate.update("insert into account values(null,?,?)","cylycgs",20000d);
}
}
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置Spring的内置连接池 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!-- 属性注入 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring4_day03"></property>
<property name="username" value="root"></property>
<property name="password" value="p@ssw0rd"></property>
</bean>
<!-- 配置Spring的JDBC的模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置Spring的内置连接池 -->
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
属性注入
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring4_day03"></property>
<property name="username" value="root"></property>
<property name="password" value="p@ssw0rd"></property>
</bean> -->
<!-- 配置DBCP连接池 -->
<!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring4_day03"></property>
<property name="username" value="root"></property>
<property name="password" value="p@ssw0rd"></property>
</bean> -->
<!-- 配置C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql:///spring4_day03"></property>
<property name="user" value="root"></property>
<property name="password" value="p@ssw0rd"></property>
</bean>
<!-- 配置Spring的JDBC的模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
jdbc.properties代码:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring4_day03
jdbc.username=root
jdbc.password=p@ssw0rd
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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置Spring的内置连接池 -->
<!-- <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
属性注入
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring4_day03"></property>
<property name="username" value="root"></property>
<property name="password" value="p@ssw0rd"></property>
</bean> -->
<!-- 配置DBCP连接池 -->
<!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///spring4_day03"></property>
<property name="username" value="root"></property>
<property name="password" value="p@ssw0rd"></property>
</bean> -->
<!-- 引入属性文件 -->
<!-- 1.通过bean标签引入 -->
<!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"></property>
</bean> -->
<!-- 2.通过context标签引入 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 配置C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置Spring的JDBC的模板 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
</beans>
JdbcDemo2代码:
package com.itheima.jdbc.demo1;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcDemo2 {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
@Test
// 保存操作
public void demo1() {
jdbcTemplate.update("insert into account values(null,?,?)","菲菲",10000d);
}
@Test
// 修改操作
public void demo2() {
jdbcTemplate.update("update account set money=? where id=?",50000d,1);
}
@Test
// 删除操作
public void demo3() {
jdbcTemplate.update("delete from account where id=?",1);
}
@Test
// 查询操作 -- 查询某个字段
public void demo4() {
String name = jdbcTemplate.queryForObject("select name from account where id=?",String.class,2 );
}
@Test
// 查询操作 -- 封装到对象中
public void demo5() {
Account account =jdbcTemplate.queryForObject("select * from account where id=?",new MyRowMapper() , 3);
System.out.println(account);
}
@Test
// 查询操作 -- 封装到对象集合中
public void demo6() {
List<Account> list =jdbcTemplate.query("select * from account",new MyRowMapper());
for (Account account : list) {
System.out.println(account);
}
}
class MyRowMapper implements RowMapper<Account>{
@Override
public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
Account account = new Account();
account.setId(rs.getInt("id"));
account.setName(rs.getString("name"));
account.setMoney(rs.getDouble("money"));
return account;
}
}
class Account{
private Integer id;
private String name;
private double money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}
}
事务可以理解为逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
以转账为例,A给B转账需要从A的账户中扣钱,并给B的账户中加钱,这两个步骤,但是如何保证这一组操作是一致性的呢?确保不会出现A的账户扣钱了,但B的账户没有收到的情况,这就需要事务了!
AccountService.java代码:
package com.itheima.tx.demo1;
/**
* 转账的业务层接口
* @author cgs
*/
public interface AccountService {
public void transfer(String from,String to,Double money);
}
AccountServiceImpl.java代码:
package com.itheima.tx.demo1;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
/**
* 转账的业务层实现类
* @author cgs
*/
public class AccountServiceImpl implements AccountService {
//注入DAO
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
//注入事务管理模板
private TransactionTemplate transactionTemplate;
public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}
@Override
/**
* from:转出账号
* to:转入账号
* money:金额
*/
public void transfer(final String from,final String to,final Double money) {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
accountDao.outMoney(from, money);//转出
int num = 1 / 0;//当使用事务时,遇到异常,A账户的钱不会减少
accountDao.inMoney(to, money);//转入
}
});
}
}
AccountDao.java代码:
package com.itheima.tx.demo1;
/**
* 转账的DAO接口
* @author cgs
*/
public interface AccountDao {
public void outMoney(String from,Double money);
public void inMoney(String to,Double money);
}
AccountDaoImpl.java代码:
package com.itheima.tx.demo1;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* 转账的DAO实现类
* @author cgs
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
//由于继承了JdbcDaoSupport类,所以tx.xml中直接配置dataSource就可以了,看JdbcDaoSupport源码
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money=money-? where name=?",money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money=money+? where name=?",money,to);
}
}
SpringDemo1.java代码:
package com.itheima.tx.demo1;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* 测试转账环境
* @author cgs
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx.xml")
public class SpringDemo1 {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void demo1() {
//转账,如果没有事务保障,就会出问题,例如转出人已扣钱,被转入人没有收到钱
accountService.transfer("如花", "菲菲", 1000d);
}
}
tx.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置Service -->
<bean id="accountService" class="com.itheima.tx.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
<!-- 注入事务管理模板 -->
<property name="transactionTemplate" ref="transactionTemplate"></property>
</bean>
<!-- 配置DAO -->
<bean id="accountDao" class="com.itheima.tx.demo1.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置连接池和JDBC模板 -->
<!-- 配置C3P0连接池 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理模板 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
</bean>
</beans>
AccountDaoImpl.java代码:
package com.itheima.tx.demo2;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* 转账的DAO实现类
* @author cgs
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
//由于继承了JdbcDaoSupport类,所以tx.xml中直接配置dataSource就可以了,看JdbcDaoSupport源码
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money=money-? where name=?",money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money=money+? where name=?",money,to);
}
}
AccountServiceImpl.java代码:
package com.itheima.tx.demo2;
/**
* 转账的业务层实现类
* @author cgs
*/
public class AccountServiceImpl implements AccountService {
//注入DAO
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
/**
* from:转出账号
* to:转入账号
* money:金额
*/
public void transfer(final String from,final String to,final Double money) {
accountDao.outMoney(from, money);
int num = 1 / 0;
accountDao.inMoney(to, money);
}
}
SpringDemo1.java代码:
package com.itheima.tx.demo2;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* 测试转账环境
* @author cgs
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx2.xml")
public class SpringDemo1 {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void demo1() {
//转账,如果没有事务保障,就会出问题,例如转出人已扣钱,被转入人没有收到钱
accountService.transfer("如花", "菲菲", 1000d);
}
}
tx2.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置Service -->
<bean id="accountService" class="com.itheima.tx.demo2.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 配置DAO -->
<bean id="accountDao" class="com.itheima.tx.demo2.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置连接池和JDBC模板 -->
<!-- 配置C3P0连接池 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务增强,也就是切面 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" isolation="DEFAULT"/>
<!-- 事务管理规则示例,此例中没用 -->
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="find" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- aop的配置 -->
<aop:config>
<aop:pointcut expression="execution(* com.itheima.tx.demo2.AccountServiceImpl.transfer(..))" id="pointcut1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>
</beans>
AccountDaoImpl.java代码:
package com.itheima.tx.demo3;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
/**
* 转账的DAO实现类
* @author cgs
*/
public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
//由于继承了JdbcDaoSupport类,所以tx.xml中直接配置dataSource就可以了,看JdbcDaoSupport源码
@Override
public void outMoney(String from, Double money) {
this.getJdbcTemplate().update("update account set money=money-? where name=?",money,from);
}
@Override
public void inMoney(String to, Double money) {
this.getJdbcTemplate().update("update account set money=money+? where name=?",money,to);
}
}
AccountServiceImpl.java代码:
package com.itheima.tx.demo3;
import org.springframework.transaction.annotation.Transactional;
/**
* 转账的业务层实现类
* @author cgs
*/
@Transactional
public class AccountServiceImpl implements AccountService {
//注入DAO
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
@Override
/**
* from:转出账号
* to:转入账号
* money:金额
*/
public void transfer(final String from,final String to,final Double money) {
accountDao.outMoney(from, money);
int num = 1 / 0;
accountDao.inMoney(to, money);
}
}
SpringDemo1.java代码:
package com.itheima.tx.demo3;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* 测试转账环境
* @author cgs
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:tx3.xml")
public class SpringDemo1 {
@Resource(name="accountService")
private AccountService accountService;
@Test
public void demo1() {
//转账,如果没有事务保障,就会出问题,例如转出人已扣钱,被转入人没有收到钱
accountService.transfer("如花", "菲菲", 1000d);
}
}
tx3.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"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 配置Service -->
<bean id="accountService" class="com.itheima.tx.demo3.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
<!-- 配置DAO -->
<bean id="accountDao" class="com.itheima.tx.demo3.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置连接池和JDBC模板 -->
<!-- 配置C3P0连接池 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 配置平台事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>