前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深圳Java培训:使用AOP功能和ThreadLocal类实现自定义事务管理

深圳Java培训:使用AOP功能和ThreadLocal类实现自定义事务管理

原创
作者头像
深圳java培训技术
修改2019-06-20 17:47:36
3920
修改2019-06-20 17:47:36
举报
文章被收录于专栏:深圳java培训深圳java培训

深圳Java培训:使用AOP功能和ThreadLocal类实现自定义事务管理

首先,需要理解ThreadLocal类的作用。ThreadLocal是为了在同一个线程中共享数据,具体原理可以参考源代码,如下: public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); } 设置值实际上就是通过map存放的,与map不同的是固定将当前线程作为key值。 public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings(“unchecked”) T result = (T)e.value; return result; } } return setInitialValue(); } 获取值时通过当前线程去获取值,所以如果在同一个线程中,前面存进去的值,后面是可以取出来用的,以达到线程共享数据的目的。

接下来的例子中,主要是把一个线程中的连接共享,以达到一个线程共享一个连接,因为只有这样,才能够做到事务操作,因为同一个事务必须要求在同一个连接中,才能保证数据安全。具体代码如下: @Component public class DBManager { /** * 使用map的方式存储数据,key使用当前线程,所以能够保证一个线程共享数据,此处用来在一个线程中共享一个数据库连接 / private ThreadLocal threadLocal = new ThreadLocal<>(); @Value("jdbc.url&quot;)//使用读取properties配置文件中的数据加载urlprivateStringurl;@Value(&quot;{jdbc.url}&quot;) // 使用读取properties配置文件中的数据加载urlprivate String url;@Value(&quot;jdbc.url")//使用读取properties配置文件中的数据加载urlprivateStringurl;@Value("{jdbc.driver}") private String driver; @Value("jdbc.user&quot;)privateStringusername;@Value(&quot;{jdbc.user}&quot;)private String username;@Value(&quot;jdbc.user")privateStringusername;@Value("{jdbc.password}") private String password; /* * 创建一个新的连接 * @return * @throws Exception */ private Connection createConnection() throws Exception { Class.forName(driver); return DriverManager.getConnection(url, username, password); } public Connection getConnection() throws Exception { // 在ThreadLocal集合中获得以当前线程为key的连接对象 Connection connection = threadLocal.get(); // 如果获取到了连接则返回连接 if (connection != null && !connection.isClosed()){ return connection; }else { // 如果连接不存在或者已经关闭则创建新的连接并把连接存到ThreadLocal集合中 connection = createConnection(); threadLocal.set(connection); return connection; } } public void closeConnection(){ // 在ThreadLocal集合中获得以当前线程为key的连接对象 Connection connection = threadLocal.get(); try { // 如果获取到了连接则关闭连接,并且将集合中设置为null if (connection != null && !connection.isClosed()){ connection.close(); threadLocal.set(null); } }catch (Exception e){ e.printStackTrace(); } } } 在service层中,由于所有的方法都需要处理业务之外的内容,比如连接开启和关闭,事务的提交回滚等,这些应该属于AOP中切面的内容,可以提取出来解决,切面代码如下:(通过设置service层的around通知完成) @Component public class MyTransaction { @Resource private DBManager dbManager; // 使用aop的around的方式处理事务 public Object doTransacition(ProceedingJoinPoint pjp){ Connection connection = null; Object result = null; // 得到实际调用的service中方法的名称 String methodName = pjp.getSignature().getName(); try { connection = dbManager.getConnection(); // 判断方法的名称是否需要事务操作(增、删、改需要事务操作) if (methodName.startsWith(“update”) || methodName.startsWith(“save”) || methodName.startsWith(“delete”)){ // 设置事务关闭自动提交 connection.setAutoCommit(false); // 实际业务方法执行 result = pjp.proceed(); // 提交事务 connection.commit(); }else { result = pjp.proceed(); } }catch (Throwable e){ e.printStackTrace(); if (connection != null){ // 判断方法的名称是否需要事务的回滚操作操作(增、删、改需要事务操作) if (methodName.startsWith(“update”) || methodName.startsWith(“save”) || methodName.startsWith(“delete”)){ try { connection.rollback(); } catch (SQLException e1) { e1.printStackTrace(); } } } }finally { // 关闭连接 dbManager.closeConnection(); } return result; } }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档