利用动态代理实现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---
可以打断点,对比数据库查看事务的执行情况。