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);//调用代理对象的代理方法