一、基础环境准备
1、定义一个mybatis Mapper接口类
package com.mybatis.Mapper;
import com.mybatis.entity.User;
public interface IUserMapper {
int insert(User user);
}
2、定义接口对应的xml文件
<?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.mybatis.Mapper.IUserMapper">
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into user(name,age,is_delete,gender) value(#{name},#{age},#{isDelete},#{gender});
</insert>
</mapper>
3、定义Service层接口
package com.mybatis.service;
import com.mybatis.entity.User;
public interface IUserService {
int insert(User user);
}
4、定义Service层的接口实现类
package com.mybatis.service.impl;
import com.mybatis.Mapper.IUserMapper;
import com.mybatis.entity.User;
import com.mybatis.service.IUserService;
public class IUserServiceImpl implements IUserService {
private IUserMapper userMapper;
public IUserServiceImpl(IUserMapper userMapper) {
super();
this.userMapper = userMapper;
}
public IUserServiceImpl() {
super();
}
@Override
public int insert(User user) {
int insert = userMapper.insert(user);
//insert/=0; //测试方法抛出异常时,事务进行回滚
return insert;
}
}
5、写Service层接口测试类
package com.mybatis.test;
import java.io.IOException;
import org.junit.Before;
import org.junit.Test;
import com.mybatis.entity.User;
import com.mybatis.proxy.AopUtil;
import com.mybatis.service.IUserService;
public class TestIUserServiceImpl {
private IUserService userService;
@Before
public void testBefore() throws IOException{
//为目标对象生产代理对象
this.userService=AopUtil.newProxy(userService);
}
//测试aop管理数据库事务
@Test
public void testInsert(){
User user = new User(null,"InsertAop",22,"四川", false);
userService.insert(user);
}
}
6、创建一个aop工具类
package com.mybatis.proxy;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.mybatis.Mapper.IUserMapper;
import com.mybatis.service.IUserService;
import com.mybatis.service.impl.IUserServiceImpl;
public class AopUtil {
/**
* SqlSessionFactory
*/
public static SqlSessionFactory sqlSessionFactory;
/**
* 创建SqlSessionFactory
* @return
* @throws IOException
*/
private static SqlSessionFactory getSqlSessionFactory() throws IOException{
String resource = "mybatis-config.xml";//类路径下,如果在其子包下mybatis/mybatis-config.xml
InputStream inputStream = Resources.getResourceAsStream(resource);
return new SqlSessionFactoryBuilder().build(inputStream);
}
/**
* 创建实现类代理对象
* @param userService
* @return
*/
public static IUserService newProxy(IUserService userService){
//创建SqlSessionFactory
try {
sqlSessionFactory=getSqlSessionFactory();
} catch (IOException e1) {
e1.printStackTrace();
System.out.println("创建SqlSessionFactory失败");
}
//创建SqlSession
SqlSession openSession = sqlSessionFactory.openSession();
//获取Mapper接口代理对象
IUserMapper userMapper=openSession.getMapper(IUserMapper.class);
//目标对象
IUserService target=new IUserServiceImpl(userMapper);
//代理对象
userService =(IUserService)Proxy.newProxyInstance(target.getClass().getClassLoader(),
new Class[]{IUserService.class},
new InvocationHandler() {
/**
* Object proxy:代理对象
* Method method:正在被调用的方法
* Object[] args:正在被调用的方法参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object invoke =null;
try {
//前置通知
before();
//执行目标方法
invoke = method.invoke(target, args);
//后置通知
after(openSession);
} catch (Exception e) {
//异常通知方法
exception(openSession);
e.printStackTrace();
}
//返回通知方法:在方法返回前通知
returnMothed(openSession);
return invoke;
}
});
return userService;
}
/**
* 前置通知方法:
*/
public static void before(){
System.out.println("我是前置通知");
around();
}
/**
* 后置通知方法:
* 1,提交事务
*/
public static void after(SqlSession openSession){
openSession.commit();
System.out.println("我是后置通知");
around();
}
/**
* 异常通知方法:
*/
public static void exception(SqlSession openSession){
openSession.rollback();
System.out.println("我是异常通知");
around();
}
/**
* 返回通知方法:在方法返回前通知
* 处理返回数据
* 关闭sqlsession
*/
public static void returnMothed(SqlSession openSession){
openSession.close();
System.out.println("我是返回前通知");
around();
}
/**
* 环绕通知方法:在整个方法运行的任何时刻
*/
public static void around(){
System.out.println("我是环绕通知");
}
}
7、测试不抛异常时提交成功
8、测试抛出异常时,自动回滚