动态代理(了解但不常用)

xiaoxiao2021-02-27  173

package com.util; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; /** * 动态代理工具类 * * @author zhaoj * */ public class ServiceProxyUtil implements InvocationHandler { private Object targertObj;// 目标对象的引用,用于在invoke方法中执行目标方法 // 根据目标对象的引用,动态创建这个引用对象的代理对象 public Object newProxyObject(Object targerObj) { this.targertObj = targerObj; // 创建动态代理对象 // 参数1 目标对象的类加载器 // 参数2 目标对象的所有父接口的Class // 参数3 某个InvocationHandler的接口对象, // 作用是:通知JVM这个代理对象在执行方法时要调用哪个类中的invoke方法 return Proxy.newProxyInstance(targerObj.getClass().getClassLoader(), targerObj.getClass().getInterfaces(), this); } /* * 动态代理的通用代理方法,当代理对象调用任何一个方法时都会自动执行这个invoke方法.JVM完成自动调用这个方法 * * 参数1 代理对象的引用,注意:这个对象最好不要使用 * 参数2 目标方法的反射引用对象 * 参数3 执行目标方法时所需要的参数列表,如果目标方法没有参数那么这个数组的长度为0 * 返回值Object 为目标方法的返回值数据,如果目标方法返回值类型为void 那么这个方法应该返回 null */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; Connection conn = DBUtil.getConn(); try { result = method.invoke(targertObj, args);//执行目标方法 conn.commit();//事务提交 } catch (Exception e) { e.printStackTrace(); conn.rollback();//事务回滚 }finally{ DBUtil.close(null, null, conn); } return result; } }

package com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * 数据库工具类 * * @author zhaoj * */ public class DBUtil { private static ThreadLocal<Connection> local = new ThreadLocal<>(); static { try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 获得数据库连接对象 * * @return */ public static Connection getConn() { // 根据当前线程对象,从容器中获取数据库连接 Connection conn = local.get(); if (conn == null) { // 如果没有数据库连接,新创建一个 try { conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mvc", "root", "root"); // 设置数据库手动提交 conn.setAutoCommit(false); } catch (SQLException e) { e.printStackTrace(); } } // 如果有的话直接返回,这样保证了同一个线程中Connection是相同的 return conn; } /** * 关闭资源 * * @param rs * @param pre * @param conn */ public static void close(ResultSet rs, PreparedStatement pre, Connection conn) { try { if (rs != null) { rs.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (pre != null) { pre.close(); } } catch (SQLException e) { e.printStackTrace(); } try { if (conn != null) { conn.close(); local.remove();// 当使用完,从容器中移出,否则容易造成内存溢出 } } catch (SQLException e) { e.printStackTrace(); } } }

如何使用:

AccountService service=(AccountService) new ServiceProxyUtil().newProxyObject(new AccountServiceImpl()); Integer result =service.transfer(fromAccount,toAccount,money);//调用代理对象的代理方法

转载请注明原文地址: https://www.6miu.com/read-10588.html

最新回复(0)