使用ThreadLocal与JDK动态代理 实现事务AOP管理
来源:互联网 发布:网络测速器在线测网速 编辑:程序博客网 时间:2024/05/20 05:10
数据库创建两张表进行测试
mysql> create table student(id int , name varchar(50));
mysql> create table classroom(id int , name varchar(50));
首先写从数据库获取连接的ConnectionUtil.java
package com.zf.util;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;public final class ConnectionUtil {private final static String username = "root";private final static String password = "root";private final static String url = "jdbc:mysql:///threadlocal";private ConnectionUtil(){}static{try {Class.forName("com.mysql.jdbc.Driver");} catch (ClassNotFoundException e) { e.printStackTrace();}}public static Connection openConnection(){Connection conn = null ;try {conn = DriverManager.getConnection(url, username, password);} catch (SQLException e) {e.printStackTrace();}return conn ;}}
然后写管理Connection的SessionManager 类似于hibernate 的 SessionFactory
package com.zf.util;import java.sql.Connection;import java.sql.SQLException;/** * 单例实现 * @author zhoufeng * */public final class SessionManager { private static ThreadLocal<Connection> session = new ThreadLocal<Connection>();private static final SessionManager sessionManager = new SessionManager() ;private SessionManager(){} ;/** * 在获取SessionManager时 ,就绑定Connection到ThreadLocal中 * @return */public static SessionManager newInstance(){try {if(session.get() == null || session.get().isClosed()){session.set(ConnectionUtil.openConnection()) ;}} catch (SQLException e) {e.printStackTrace(); }return sessionManager; }public Connection getCurrentSession(){return session.get() ;}public void beginTransaction(){try {session.get().setAutoCommit(false);} catch (SQLException e) {e.printStackTrace();}}public void rollback(){try {session.get().rollback() ;session.get().close();} catch (SQLException e) {e.printStackTrace();}}public void commit(){try {session.get().commit() ;session.get().close();} catch (SQLException e) {e.printStackTrace();}}}
然后是操作数据库两张表的Dao
package com.zf.dao;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import com.zf.util.SessionManager;public class ClassRoomDao {public boolean addClassRoom(int id , String name) throws SQLException{String sql = "insert into classroom values(? , ?)";Connection conn = SessionManager.newInstance().getCurrentSession() ;System.out.println(Thread.currentThread().getId() + " addClassRoom " + conn);PreparedStatement ps = conn.prepareStatement(sql);ps.setInt(1, id); ps.setString(2, name);int count = ps.executeUpdate();return count > 0 ; }}
package com.zf.dao;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import com.zf.util.SessionManager;public class StudentDao {public boolean addStudent(int id , String name) throws SQLException{String sql = "insert into student values(? , ?)";Connection conn = SessionManager.newInstance().getCurrentSession() ;System.out.println(Thread.currentThread().getId() + " addStudent " + conn);PreparedStatement ps = conn.prepareStatement(sql);ps.setInt(1, id);ps.setString(2, name);int count = ps.executeUpdate();return count > 0 ; }}
接下来就定义Service接口 并实现
package com.zf.service;import java.sql.SQLException;public interface SCService {void addStudent(int id , String name) throws SQLException;}
package com.zf.service;import java.sql.SQLException;import com.zf.dao.ClassRoomDao;import com.zf.dao.StudentDao;import com.zf.util.SessionManager;public class SCServiceImpl implements SCService{public void addStudent(int id , String name) throws SQLException{StudentDao sd = new StudentDao() ;ClassRoomDao cr = new ClassRoomDao() ;sd.addStudent(id, name); if(id > 8) //测试是否会回滚事务throw new RuntimeException("my exception");cr.addClassRoom(id, name); }}
接下来的就是实现AOP事务管理的关键了。 使用JDK动态代理,为Service加入事务
package com.zf.util;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 用该类来代理Service , 为需要代理的Service加入事务 。 * 实现AOP事务管理 * @author zhoufeng * */public class ServiceFactory {public static Object proxyService(final Object obj , final Class<?>[] inf){Object proxyService = Proxy.newProxyInstance(obj.getClass().getClassLoader(), inf , new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {SessionManager sm = SessionManager.newInstance();Object result = null ;try {sm.beginTransaction() ;result = method.invoke(obj, args);sm.commit();} catch (Exception e) {sm.rollback();e.printStackTrace();}return result;}}) ;return proxyService ;}}
测试
package com.zf.test;import java.sql.SQLException;import com.zf.service.SCService;import com.zf.service.SCServiceImpl;import com.zf.util.ServiceFactory;public class Test01 {public static void main(String[] args) {final SCService ss = (SCService) ServiceFactory.proxyService(new SCServiceImpl() , new Class[]{SCService.class});/** * 用两条线程分别执行service方法 * 结果会看到同一条线程中 各个Dao中获取的Connection是相同的 * 第二条线程发生了异常,并且事务回滚了 */new Thread(new Runnable() {@Overridepublic void run() {try {ss.addStudent(8, "name8");} catch (SQLException e) {e.printStackTrace();}}}).start();new Thread(new Runnable() {@Override public void run() {try {ss.addStudent(9, "name9");} catch (SQLException e) {e.printStackTrace();}}}).start();}}
- 使用ThreadLocal与JDK动态代理 实现事务AOP管理
- JDK动态代理实现AOP
- JDK 动态代理 & AOP实现动态代理
- JDK核心API:使用动态代理实现AOP功能
- 使用JDK中的Proxy技术实现AOP功能[动态代理]
- AOP之JDK 动态代理使用及实现原理分析
- JDK动态代理和CGLIB动态代理,实现Spring注解管理事务区别。
- jdk动态代理与cglib代理、spring aop代理实现原理
- 利用jdk动态代理实现aop
- JDK动态代理实现简单AOP--转
- AOP的JDK动态代理实现
- JDK动态代理与Spring AOP
- 分析动态代理Java JDK 动态代理(AOP)使用及实现原理分析
- spring(AOP)静态代理、JDK动态代理、cglib实现代理
- AOP的底层实现--JDK动态代理,CGLIB动态代理
- 使用反射生成JDK动态代理---动态代理和AOP
- JDK动态代理结合ThreadLocal实现Hibernate的事务管理
- AOP实现--JDK中的动态代理和cglib代理
- discuz安装提示ucenter url有误
- I2C设备驱动编写,struct i2c_device_id,struct i2c_driver,i2c_add_driver,i2c_register_board_info
- OpenStack的架构详解(7)
- 什么是图形加速卡(四)
- C++ vector容器使用 排序
- 使用ThreadLocal与JDK动态代理 实现事务AOP管理
- 获取上个月第一天和最后一天日期
- OpenStack的架构详解(8)
- php代码优化方法,加速运行速度的技巧总结
- opencv中CvSeq的用法
- PHP使用PEAR的auth_http类库用身份校验
- WPF - ListBox显示任意内容
- C语言socket判断网络是否联通(支持域名/附源码)
- OpenStack的架构详解(9)