MyBatis 简单代码讲解动态代理原理

先运行mybatis例子

public class SqlSessionFactoryTest {
	public static void main(String[] args) throws IOException {
		String resource = "mybatis/mybatis-config.xml";
		Reader reader = Resources.getResourceAsReader(resource);
		SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
		SqlSessionFactory sqlSessionFactory = builder.build(reader);
		System.out.println(sqlSessionFactory);
	}
}

运行结果

DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
DEBUG [main] - PooledDataSource forcefully closed/removed all connections.
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory@1d56ce6a
DEBUG [main] - Created connection 1865127310.
DEBUG [main] - ooo Connection Opened
DEBUG [main] - ==>  Executing: select * from Role where id = ? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==    Columns: id, name, desc
DEBUG [main] - <==        Row: 1, name, test
org.mybatis.example.domain.Role@16b3fc9e

以上代码对应分析的源码过程

下面的例子不用在意,可直接跳过
在这里插入图片描述

核心代码演示

jdbc访问数据库
public class MySQLDemo {
	static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
	static final String DB_URL = "jdbc:mysql://127.0.0.1/mybatis";

	// 数据库的用户名与密码,需要根据自己的设置
	static final String USER = "root";
	static final String PASS = "root";

	public static void main(String[] args) {
		Connection conn = null;
		Statement stmt = null;
		try {
			// 注册 JDBC 驱动
			Class.forName(JDBC_DRIVER);

			// 打开链接
			System.out.println("连接数据库...");
			conn = DriverManager.getConnection(DB_URL, USER, PASS);

			// 执行查询
			System.out.println(" 实例化Statement对象...");
			stmt = conn.createStatement();
			String sql;
			sql = "select * from Role";
			ResultSet rs = stmt.executeQuery(sql);

			// 展开结果集数据库
			while (rs.next()) {
				// 通过字段检索
				int id = rs.getInt("id");
				String name = rs.getString("name");
				String desc = rs.getString("desc");

				// 输出数据
				System.out.print("ID: " + id);
				System.out.print(", 名称: " + name);
				System.out.print(", 描述: " + desc);
				System.out.print("\n");
			}
			// 完成后关闭
			rs.close();
			stmt.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (stmt != null)
					stmt.close();
			} catch (SQLException se2) {
			}
			try {
				if (conn != null)
					conn.close();
			} catch (SQLException se) {
			}
		}
		System.out.println("Goodbye!");
	}
}

运行结果

连接数据库...
 实例化Statement对象...
ID: 1, 名称: name, 描述: test
Goodbye!
核心功能改造

将上述jdbc访问改造为工具类

public class SQLUtils {
	static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
	static final String DB_URL = "jdbc:mysql://127.0.0.1/mybatis";

	// 数据库的用户名与密码,需要根据自己的设置
	static final String USER = "root";
	static final String PASS = "root";

	public static void executeSql(String sql) {
		Connection conn = null;
		Statement stmt = null;
		try {
			// 注册 JDBC 驱动
			Class.forName(JDBC_DRIVER);

			// 打开链接
			System.out.println("连接数据库...");
			conn = DriverManager.getConnection(DB_URL, USER, PASS);

			// 执行查询
			System.out.println(" 实例化Statement对象...");
			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(sql);

			// 展开结果集数据库
			while (rs.next()) {
				// 通过字段检索
				int id = rs.getInt("id");
				String name = rs.getString("name");
				String desc = rs.getString("desc");

				// 输出数据
				System.out.print("ID: " + id);
				System.out.print(", 名称: " + name);
				System.out.print(", 描述: " + desc);
				System.out.print("\n");
			}
			// 完成后关闭
			rs.close();
			stmt.close();
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (stmt != null)
					stmt.close();
			} catch (SQLException se2) {
			}
			try {
				if (conn != null)
					conn.close();
			} catch (SQLException se) {
			}
		}
		System.out.println("Goodbye!");
	}
}

定义接口

public interface RoleDao {
	void query();
}

这里不定义xml,直接定义json,新建文件:priv.dengjili.mybatis.example.proxy.RoleDao.json

{
	"query":"select * from Role"
}

核心代理类

public class MethodProxy implements InvocationHandler {

	private String filePath;
	
	public MethodProxy(String filePath) {
		this.filePath = filePath;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		String content = FileUtils.readFileToString(new File(filePath), Charset.defaultCharset());
		JSONObject jsonObject = JSONObject.parseObject(content);
		String sql = jsonObject.getString(method.getName());
		SQLUtils.executeSql(sql);
		return null;
	}

  public static <T> T newMethodProxy(Class<T> mapperInterface, String filePath) {
	    ClassLoader classLoader = mapperInterface.getClassLoader();
	    Class[] interfaces = new Class[]{mapperInterface};
	    MethodProxy proxy = new MethodProxy(filePath);
	    return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
	  }
}

测试类

public class ProxyTest {
	public static void main(String[] args) {
		RoleDao dao = MethodProxy.newMethodProxy(RoleDao.class, "C:/temp-workspace/workspace/mybatis-handwritten/src/main/resources/priv.dengjili.mybatis.example.proxy.RoleDao.json");
		dao.query();
	}
}

运行结果

连接数据库...
 实例化Statement对象...
ID: 1, 名称: name, 描述: test
Goodbye!

mybatis主要思想也就是上述思想

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值