Java动态代理实现类似Spring AOP的简单数据库事务管理

一、基础环境准备

    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、测试抛出异常时,自动回滚

        

 

    

 

转载于:https://my.oschina.net/zhaomin/blog/1590805

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值