从零实现MVC框架之AOP事务(5)

利用动态代理实现AOP。另外我么写一个注解,表明哪个类下的方法需要加事务(为了简单偷懒了,哈...)。加上注解后

此类的每个方法都会加事务。

这其中还多了一个事务执行器的概念,事务执行器和一般执行器的区别就是 事务执行器中数据库连接是不自动提交的。

而一般执行器中的连接是自动提交的。 我们使用ThreadLocal来保存事务执行器,来保证每个线程都有自己的事务执行器。

下面看具体实现。

注解

package com.hc.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 事务类注解
 * @author chuer
 * @date 2014-7-16 下午2:28:12
 * @version V1.0
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Transaction {

}


抽象实体类修改setExecute和rollBack方法(AbstractEntity)

@Override
	public void setExecute() {
		AbstractExecute<AbstractEntity> execute2 = TransactionManager.getInstance().getExecute();
		if(execute2 != null){
			execute = execute2;
		}else{
			execute = ExecuteFactory.getExecute();
		}
	}

	@Override
	public void rollBack() {
		AbstractExecute<AbstractEntity> execute2 = TransactionManager.getInstance().getExecute();
		if(execute2 != null){
			execute2.rollback();
		}
	}
	

事务类缓存

package com.hc.transaction;

import java.io.File;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import com.hc.annotation.Transaction;
/**
 * 
 * @author chuer
 * @date 2014-7-16 下午3:32:49
 * @version V1.0
 */
public class TransactionProxyCache {

	public static ConcurrentHashMap<Class<?>,Object> cache = new ConcurrentHashMap<>();
	public static final String PAKAGE = "com";//扫描的包名 根据自己的包名进行修改
	public static final String PAKAGE_SOURCE = "/com/hc";//扫描的包名 根据自己的包名进行修改
	public static final String SECOND_PAKAGE = "com.hc";//扫描的包名 根据自己的包名进行修改
	static{
		//扫描项目下所有的类
		try {
			init();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static void init(){
		String path = TransactionProxyCache.class.getResource(PAKAGE_SOURCE).getPath();
		List<String> classes = new ArrayList<String>();
		getAllClasses(new File(path),classes);
		
		//实例化
		for(String p : classes){
			try{
				Class<?> cls = Class.forName(p);
				if(cls.isAnnotationPresent(Transaction.class)){
					Object newInstance = cls.getConstructor(new Class[]{}).newInstance(new Object[]{});
					Object newProxyInstance = Proxy.newProxyInstance(newInstance
							.getClass().getClassLoader(), newInstance.getClass()
							.getInterfaces(), new AOPHandler(newInstance));
					cache.put(cls, newProxyInstance);
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
	}
	
	private static void getAllClasses(File file,List<String> files){
		if(file.isDirectory()){
			File[] listFiles = file.listFiles();
			for(File f : listFiles){
				getAllClasses(f,files);
			}
		}else{
			if(file.getAbsolutePath().endsWith(".class")){
				String substring = file.getAbsolutePath().substring(file.getAbsolutePath().indexOf(PAKAGE));
				substring = substring.substring(0, substring.lastIndexOf('.'));
				if(substring.contains("/")){
					substring = substring.replaceAll("/", ".");
				}else{
					substring = substring.replaceAll("\\\\", ".");
				}
				if(substring.contains(SECOND_PAKAGE)){
					files.add(substring);
				}
			}
		}
	}
	
	public static void main(String[] args) {
		
	}
	
}


动态代理AOP

package com.hc.transaction;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;


public class AOPHandler implements InvocationHandler{

	private Object obj;
	public AOPHandler(Object obj){
		this.obj = obj;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		
		//开启事务
		System.out.println("begin transaction---");
		TransactionManager.getInstance().beginTransaction();
		//执行方法
		method.invoke(obj, args);
		
		//提交事务
		TransactionManager.getInstance().commitTransaction();
		System.out.println("end transaction---");
		
		return null;
	}

	
}

 

事务管理类

package com.hc.core;


public interface ITransaction {

	public void beginTransaction();
	public void commitTransaction();
	public AbstractExecute<AbstractEntity> getExecute();
}


 

package com.hc.transaction;

import com.hc.core.AbstractEntity;
import com.hc.core.AbstractExecute;
import com.hc.core.ExecuteFactory;
import com.hc.core.ITransaction;
/**
 * 事务管理
 * @author chuer
 * @version 2014-6-16  下午1:55:06
 */
public class TransactionManager implements ITransaction{

	
	private static ThreadLocal<AbstractExecute<AbstractEntity>> local = new ThreadLocal<>();
	private static TransactionManager manager = new TransactionManager();
	private TransactionManager(){}
	
	public static TransactionManager getInstance(){
		return manager;
	}
	
	@Override
	public void beginTransaction() {
		AbstractExecute<AbstractEntity> execute = ExecuteFactory.getTransactionExecute();
		execute.setAutoCommit(false);
		local.set(execute);
	}

	@Override
	public void commitTransaction() {
		AbstractExecute<AbstractEntity> execute = getExecute();
		execute.commit();
		local.remove();
	}

	@Override
	public AbstractExecute<AbstractEntity> getExecute() {
		return  local.get();
	}

	
	
}



事务类

package com.hc.sample.service;

import java.sql.SQLException;

public interface UserService {

	public void add()throws SQLException;
	
}


 

package com.hc.sample.service;

import java.sql.SQLException;

import com.hc.annotation.Transaction;
import com.hc.pool.IDPool;
import com.hc.sample.entity.UserEntity;

@Transaction
public class UserServiceImpl implements UserService{

	@Override
	public void add() throws SQLException {
		UserEntity user = new UserEntity();
		user.setId(IDPool.getInstance().applyId());
		
		user.setName("chujiinhui");
		
		//持久化用户
		user.persist();
		
		//修改用户
		user.setName("wangmanman");
		
		//异常事务回滚
	}

	
}


测试类

package com.hc.sample.startup;

import java.sql.SQLException;

import com.hc.sample.service.UserService;
import com.hc.sample.service.UserServiceImpl;
import com.hc.transaction.TransactionProxyCache;

public class TestTransaction {

	/**
	 * @param args
	 * @throws SQLException 
	 */
	public static void main(String[] args) throws SQLException {
		
		UserService userService = (UserService)TransactionProxyCache.cache.get(UserServiceImpl.class);
		
		userService.add();
	}

}


运行测试类,输出如下:

begin transaction---
insert into user_m(id,name) values (?,?)
update user_m set name=? where id=?
end transaction---

可以打断点,对比数据库查看事务的执行情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值