Spring03
SpringAOP机制详解
AOP概述
-
AOP介绍
- AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。弥补了面向对象的不足。
- 面向对象:结构化单元class
- 面向切面:结构化的单元切面(从多个类中抽离具有共性的方法),深入到类的内部方法
-
AOP编程思想
- AOP面向切面编程是一种编程思想,是OOP的延续(class),是软件开发的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型,利用AOP可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各个部分之间的耦合度降低,提高程序的可重用行,同时提高开发效率
-
SpringAOP常用术语
- Pointcut(切点):所谓切入点指对Joinpoint进行拦截的定义(影响方法的共同点)
- Advice(通知/增强):所谓通知是指拦截到Joinpoint之后所要做的事情就是通知
通知的类型:前置通知、后置通知、异常通知、最终通知、环绕通知。 - Aspect(切面):使切入点和通知的结合
- Joinpoit(连接点):正在执行的切入方法,在spring中,这些点指的使方法,spring只支持方法类型的连接点
- Target(目标对象):代理的目标对象
- Proxy(代理):一个类被AOP织入增强后,就产生一个结果代理类
- Introduction(引介):引介是一种特殊的通知在不修改代码的前提下,Introduction可以在运行期为类动态的添加一些方法或Field。(将外部内容添加到内部核心代码的过程)
-
AOP的作用及优势(解耦)
- 作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
- 优势:减少重复代码,提高开发效率,并且便于维护
Spring基于XML的AOP配置
-
环境搭建
构建maven工程添加依赖
<properties>
<spring.version>5.2.5.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
</dependencies>
沿用转账业务的代码
准备实体类,业务层和持久层代码。我们沿用上一章节中的代码即可。
创建 Spring 的配置文件并导入约束
<?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">
</beans>
配置 Spring 的 IOC
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!-- 配置Connection的工具类 ConnectionUtils -->
<bean id="connectionUtils" class="com.offcn.utils.ConnectionUtils">
<!-- 注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置queryRunner-->
<bean id="queryRunner" class="org.apache.commons.dbutils.QueryRunner"></bean>
<!--配置accountDao-->
<bean id="accountDao" class="com.offcn.dao.impl.AccountDaoImpl">
<property name="queryRunner" ref="queryRunner"></property>
<property name="connectionUtils" ref="connectionUtils"></property>
</bean>
<!--配置accountService-->
<bean id="accountService" class="com.offcn.service.impl.AccountServiceImpl">
<property name="accountDao" ref="accountDao"></property>
</bean>
抽取公共代码制作成通知
/**
* 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
*/
public class TransactionManager {
private ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils) {
this.connectionUtils = connectionUtils;
}
/**
* 开启事务
*/
public void beginTransaction(){
try {
connectionUtils.getThreadConnection().setAutoCommit(false);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 提交事务
*/
public void commit(){
try {
connectionUtils.getThreadConnection().commit();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 回滚事务
*/
public void rollback(){
try {
connectionUtils.getThreadConnection().rollback();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 释放连接
*/
public void release(){
try {
connectionUtils.removeConnection();
connectionUtils.getThreadConnection().close();//还回连接池中
}catch (Exception e){
e.printStackTrace();
}
}
}
- AOP 配置步骤
把通知类用 bean 标签配置起来
<!--配置通知:txManager-->
<bean id="txManager" class="com.offcn.utils.TransactionManager">
<property name="connectionUtils" ref="connectionUtils"></property>
</bean>
使用 aop:config 声明 AOP 配置
aop:config:
作用: 开始声明aop配置
<aop:config>
<!-- 配置的代码都写在此处 -->
</aop:config>
使用 aop:aspect 配置切面
aop:aspect
作用: 用于配置切面
属性:
id :给切面提供一个唯一标识。
ref:引用配置好的通知类 bean 的 id。
<aop:aspect id="tdAdvice" ref="txManager">
<!--配置通知的类型要写在此处-->
</aop:aspect>
使用 aop:pointcut 配置切入点表达式
aop:pointcut
作用: 用于配置切入点表达式。就是指定对哪些类的哪些方法进行增强。
属性: expression:用于定义切入点表达式。
id:用于给切入点表达式提供一个唯一标识
<aop:pointcut id="point1"
expression="execution( public void com.offcn.service.impl.AccountServiceImpl.transfer(java.lang.String,java.lang.String,java.lang.Double))"/>
使用 aop:xxx 配置对应的通知类型
aop:before
作用:用于配置前置通知。指定增强的方法在切入点方法之前执行
属性:
method:用于指定通知类中的增强方法名称
ponitcut-ref:用于指定切入点的表达式的引用
poinitcut:用于指定切入点表达式
执行时间点:
切入点方法执行之前执行
<aop:before method="beginTransaction" pointcut-ref="point1"></aop:before>
aop:after-returning
作用:
用于配置后置通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
执行时间点:
切入点方法正常执行之后。它和异常通知只能有一个执行
<aop:after-returning method="commit" pointcut-ref="point1"/>
aop:after-throwing
作用:
用于配置异常通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
执行时间点:
切入点方法执行产生异常后执行。它和后置通知只能执行一个
<aop:after-throwing method="rollback" pointcut-ref="point1"/>
aop:after
作用:
用于配置最终通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
执行时间点:
无论切入点方法执行时是否有异常,它都会在其后面执行。
<aop:after method="release" pointcut-ref="point1"/>
- 切入点表达式说明
切点表达式的语法
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
- 访问修饰符可以省略
- 返回值类型、包名、类名、方法名可以使用星号* 代表任意
- 包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
- 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
例如:
全匹配方式
public void
com.ujiuye.service.impl.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
访问修饰符可以省略
void com.ujiuye.service.impl.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
返回值可以使用*号,表示任意返回值
* com.ujiuye.service.impl.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
包名可以使用 * 号,表示任意包,但是有几级包,需要写几个 *
* *.*.*.*.AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
使用..来表示当前包,及其子包
* com..AccountServiceImpl.saveAccount(com.ujiuye.domain.Account)
类名可以使用*号,表示任意类
* com..*.saveAccount(com.ujiuye.domain.Account)
方法名可以使用*号,表示任意方法
* com..*.*( com.ujiuye.domain.Account)
参数列表可以使用*,表示参数可以是任意数据类型,但是必须有参数
* com..*.*(*)
参数列表可以使用..表示有无参数均可,有参数可以是任意类型
* com..*.*(..)
全通配方式:
* *..*.*(..)
注意: 通常情况下,我们都是对业务层的方法进行增强,所以切入点表达式都是切到业务层实现类。
execution(* com.ujiuye.service.impl.*.*(..))
约定优于配置:命名规范
- 环绕通知配置事务管理
在TransactionManager类当中添加方法
/**
* 环绕通知:
* spring 框架为我们提供了一个接口:ProceedingJoinPoint,它可以作为环绕通知的方法参数。
* 在环绕通知执行时,spring 框架会为我们提供该接口的实现类对象,我们直接使用就行。
* @param pjp
* @return
*/
public Object transactionAround(ProceedingJoinPoint pjp) {
//定义返回值
Object returnValue = null;
try {
//获取方法执行所需的参数
Object[] args = pjp.getArgs();
//前置通知:开启事务
beginTransaction();
//执行方法
returnValue = pjp.proceed(args);
//后置通知:提交事务
commit();
}catch(Throwable e) {
//异常通知:回滚事务
rollback();
e.printStackTrace();
}finally {
//最终通知:释放资源
release();
}
return returnValue;
}
aop:around:
作用:
用于配置环绕通知
属性:
method:指定通知中方法的名称。
pointct:定义切入点表达式
pointcut-ref:指定切入点表达式的引用
说明:
它是 spring 框架为我们提供的一种可以在代码中手动控制增强代码什么时候执行的方式。
注意:通常情况下,环绕通知都是独立使用的
<aop:config>
<aop:aspect id="tdAdvice" ref="txManager">
<aop:pointcut id="point1" expression="execution(* com.offcn.service.impl.*.*(..))"/>
<!-- 配置环绕通知 -->
<aop:around method="transactionAround" pointcut-ref="point1"/>
</aop:aspect>
</aop:config>
Spring基于注解的AOP配置
/**
* 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
*/
@Component("txManager")
public class TransactionManager {
@Autowired
private ConnectionUtils connectionUtils;
}
在通知类上使用@Aspect 注解声明为切面
/**
* 和事务管理相关的工具类,它包含了,开启事务,提交事务,回滚事务和释放连接
*/
@Component("txManager")
@Aspect //表明当前类是一个切面类
public class TransactionManager {
@Autowired
private ConnectionUtils connectionUtils;
}
在增强的方法上使用注解配置通知
@PointCut("execution(* com.offcn.service.impl.*.*(..)))");
public void pt(){}
@Before
作用:
把当前方法看成是前置通知
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
//开启事务
@Before("pt()")
public void beginTransaction(){
try {
System.out.println("before..........................");
connectionUtils.getThreadConnection().setAutoCommit(false);
}catch (Exception e){
e.printStackTrace();
}
}
@AfterReturning
作用:
把当前方法看成是后置通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用
// 提交事务
@AfterReturning("execution(* com.offcn.service.impl.*.*(..)))")
public void commit(){
try {
connectionUtils.getThreadConnection().commit();
}catch (Exception e){
e.printStackTrace();
}
}
@AfterThrowing
作用:
把当前方法看成是异常通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用
//回滚事务
@AfterThrowing("execution(* com.offcn.service.impl.*.*(..)))")
public void rollback(){
try {
connectionUtils.getThreadConnection().rollback();
}catch (Exception e){
e.printStackTrace();
}
}
@After
作用:
把当前方法看成是最终通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用
//释放连接
@After("execution(* com.offcn.service.impl.*.*(..)))")
public void release(){
try {
connectionUtils.removeConnection();
connectionUtils.getThreadConnection().close();//还回连接池中
}catch (Exception e){
e.printStackTrace();
}
}
在 spring 配置文件中开启 spring 对注解 AOP 的支持
<!-- 开启 spring 对注解 AOP 的支持 -->
<aop:aspectj-autoproxy/>
环绕通知注解配置
@Around
作用:
把当前方法看成是环绕通知。
属性:
value:用于指定切入点表达式,还可以指定切入点表达式的引用。
// 环绕通知:
@Around("execution(* com.offcn.service.impl.*.*(..)))")
public Object transactionAround(ProceedingJoinPoint pjp) {
//定义返回值
Object returnValue = null;
try {
//获取方法执行所需的参数
Object[] args = pjp.getArgs();
//前置通知:开启事务
beginTransaction();
//执行方法
returnValue = pjp.proceed(args);
//后置通知:提交事务
commit();
}catch(Throwable e) {
//异常通知:回滚事务
rollback();
e.printStackTrace();
}finally {
//最终通知:释放资源
release();
}
return returnValue;
}
切入点表达式注解
@Pointcut("execution(* com.offcn.service.impl.*.*(..))")
private void point1() {}
// 环绕通知:
@Around("point1()")///注意:千万别忘了写括号
public Object transactionAround(ProceedingJoinPoint pjp) {
//定义返回值
Object returnValue = null;
try {
//获取方法执行所需的参数
Object[] args = pjp.getArgs();
//前置通知:开启事务
beginTransaction();
//执行方法
returnValue = pjp.proceed(args);
//后置通知:提交事务
commit();
}catch(Throwable e) {
//异常通知:回滚事务
rollback();
e.printStackTrace();
}finally {
//最终通知:释放资源
release();
}
return returnValue;
}
Spring事务详解(利用了aop的思想)
Spring基于XML的事务配置
配置事务管理器
<!--平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
配置事务的通知引用事务管理器
<!--事务的配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
</tx:advice>
配置事务的属性
<!--
指定方法名称:是业务核心方法
read-only:是否是只读事务。默认 false,不只读。
isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
propagation:指定事务的传播行为。
timeout:指定超时时间。默认值为:-1。永不超时。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。
没有默认值,任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回
滚。没有默认值,任何异常都回滚。
-->
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
配置 AOP 切入点表达式
<!--事务的aop增强-->
<aop:config>
<aop:pointcut id="myPointcut" expression="execution(* com.offcn.service.impl.*.*(..))"/>
</aop:config>
配置切入点表达式和事务通知的对应关系
<!--在aop:config标签内部:建立事务的通知和切入点表达式的关系-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"></aop:advisor>
Spring基于注解的事务配置
<!-- 配置事务管理器 -->
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
在业务层使用@Transactional 注解
/**
该注解的属性和 xml 中的属性含义一致。该注解可以出现在接口上,类上和方法上。
出现接口上,表示该接口的所有实现类都有事务支持。
出现在类上,表示类中所有方法有事务支持
出现在方法上,表示方法有事务支持。
以上三个位置的优先级:方法>类>接口
*/
@Service("accountService")
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class AccountServiceImpl implements AccountService {
//依赖dao层
@Autowired
private AccountDao accountDao ;
@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
@Override
public void transfer(String sourceAccountName, String targetAccountName, Double money) {
Account sAccount = accountDao.findByName(sourceAccountName);
Account tAccount = accountDao.findByName(targetAccountName);
//来源账户减钱,目标账户加钱
sAccount.setMoney(sAccount.getMoney()-money);
tAccount.setMoney(tAccount.getMoney()+money);
//持久化到数据库
accountDao.update(sAccount);
//模拟异常发生
//int i=1/0;
accountDao.update(tAccount);
}
}
在配置文件中开启 Spring 对注解事务的支持
<!-- 开启 spring 对注解事务的支持 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
Spring整合Mybatis实现用户的CRUD
构建maven工程,添加技术依赖
<properties>
<spring.version>5.3.4</spring.version>
</properties>
<dependencies>
<!--导入junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--导入spring的context坐标-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!--导入Jdbc模块依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!--导入Mysql 驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!--导入C3P0连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!--aop-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
<!--mybatis-Spring适配包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.0</version>
</dependency>
<!-- mybatis orm框架 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
</dependencies>
构建数据库表并创建实体User
create table User(
id int primary key auto_increment,
name varchar(32) not null,
address varchar(32) not null,
birthday date
);
public class User implements Serializable {
private Integer id;
private String name;
private String address;
private Date birthday;
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 String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", address='" + address + '\'' +
", birthday=" + birthday +
'}';
}
}
编写dao层的接口UserMapper
public interface UserMapper {
int insert(User user);
int update(User user);
int delete(Integer id);
User findById(Integer id);
List<User> findAll();
}
构建mapper接口对应的sql配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.offcn.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.offcn.pojo.User">
<id column="id" jdbcType="INTEGER" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="address" jdbcType="VARCHAR" property="address" />
<result column="birthday" jdbcType="DATE" property="birthday" />
</resultMap>
<insert id="insert" parameterType="com.offcn.pojo.User">
insert into user (name, birthday, address)
values (#{name}, #{birthday},#{address})
</insert>
<update id="update">
update user
set
name= #{name},
birthday=#{birthday},
address = #{address}
where id=#{id}
</update>
<delete id="delete">
delete from user
where id =#{id}
</delete>
<select id="findById" resultMap="BaseResultMap">
select * from user where id=#{id}
</select>
<select id="findAll" resultMap="BaseResultMap">
select * from user
</select>
</mapper>
构建服务层接口UserService
public interface UserService {
int insert(User user);
int update(User user);
int delete(Integer id);
User findById(Integer id);
List<User> findAll();
}
构建服务层实现类UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public int insert(User user) {
int num = userMapper.insert(user);
return num;
}
@Override
public int update(User user) {
int num = userMapper.update(user);
return num;
}
@Override
public int delete(Integer id) {
int num = userMapper.delete(id);
return num;
}
@Override
public User findById(Integer id) {
User user = userMapper.findById(id);
return user;
}
@Override
public List<User> findAll() {
List<User> userList = userMapper.findAll();
return userList;
}
}
构建Spring框架的配置文件applicationContext.xml,配置IOC管理的对象
<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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启包扫描-->
<context:component-scan base-package="com.offcn"> </context:component-scan>
<!-- 配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--连接数据库的必备信息-->
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
<property name="user" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--Mybatis 核心对象: 工厂对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--工厂创建必须注入一个数据源-->
<property name="dataSource" ref="dataSource"/>
<!--指定mapper文件位置-->
<property name="mapperLocations" value="classpath:com/offcn/mapper/*Mapper.xml"></property>
<!--引入Mybatis的核心配置文件:
如果Mybaits的核心配置要保留,需要再此处配置:
-->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!--别名配置-->
<property name="typeAliasesPackage" value="com/offcn/pojo"/>
<!--进行分页插件的配置-->
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<value>
helperDialect=MySQL
reasonable=true
supportMethodsArguments=true
params=count=countSql
autoRuntimeDialect=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<!--配置接口的扫描-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定了包: 能够将包下的接口生成实现类: -->
<property name="basePackage" value="com.offcn.mapper"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
<!--配置平台管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class TestAccountTransfer {
@Autowired
private UserService userService;
//save
@Test
public void testInsert(){
User user = new User();
user.setName("admin");
user.setAddress("china");
user.setBirthday(new Date());
int num = userService.insert(user);
System.out.println("num:"+num);
}
//update
@Test
public void testUpdate(){
User user = new User();
user.setName("marry");
user.setAddress("America");
user.setBirthday(new Date());
user.setId(1);
int num = userService.update(user);
System.out.println("num:"+num);
}
//delete:
@Test
public void testDelete(){
int num = userService.delete(1);
System.out.println("num:"+num);
}
//findById
@Test
public void testFindById(){
User user = userService.findById(2);
System.out.println("user:"+user);
}
//findAll
@Test
public void testFindByAll(){
List<User> userList = userService.findAll();
System.out.println("userList:"+userList);
}
}

浙公网安备 33010602011771号