底层代码逻辑模拟(线程池、BeanHandler、QueryRunner类)

在使用别人的框架时,框架中会有很多符合我们需求的方法,一般情况下我们只用熟练掌握如何使用即可,对于框架而言,万变不离其宗,我们如果了解底层的运行逻辑,不仅可以加深我们对框架使用的理解,也能在我们自身拥有封装搭建框架时完善自身的框架。

于是我打算保存一些简易化的底层代码实现,以便日后回顾和优化。

线程池简易模拟:

package com.util.Connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;

/**
 *  模拟 数据库连接池,管理,分配连接对象
 * @author qiufen
 *     连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,
 *     当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。
 *     使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。
 *     而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、
 *     连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。
 *
 */
public class ConnectionPool {
	
	private  List<Connection>  list=new ArrayList<>(); //连接池
	
	int initialSize; //初始连接数
	
    public ConnectionPool(int initialSize) {
    	this.initialSize=initialSize;
    	init();
    }
    
    // 系统初始化
    public void init() {
    	try {
			//创建size个连接对象,存储在list集合中
			Class.forName("com.mysql.jdbc.Driver");
			for(int i=0;i<initialSize;i++) {
				String url="jdbc:mysql://localhost:3306/j2005_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai";
				Connection conn=DriverManager.getConnection(url, "root", "123456");
				list.add(conn);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    //用户需要连接对象的时候,并不是重新创建,而是直接从连接池中获取
    public synchronized Connection getConnection() {
    	while(list.isEmpty()) { //如果没有可用的连接对象,则进入等待
    		try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
    	}
    	
    	Connection conn=list.remove(0); //直接获取连接对象使用
    	return conn;
    }
    

   // 使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。
    
    public synchronized void returnConn(Connection conn) {
    	list.add(conn);
    	this.notifyAll(); //唤醒在连接池上等待的其他线程,可以使用连接对象
    }
}

模拟BeanHandler处理器:

package com.pojo.DataBaseConn;

import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.dbutils.ResultSetHandler;

/**
 * 将结果集转换成java对象
 * 
 * @author qiufen
 *
 * @param <T>
 */
public class BeanHandler<T> implements ResultSetHandler<T> {

	private final Class<? extends T> type;

	public BeanHandler(Class<? extends T> type) {
		this.type = type;
	}

	@Override
	public T handle(ResultSet rs) throws SQLException {
		T obj = null;
		if (rs != null) {
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				ResultSetMetaData metaData = rs.getMetaData();
				int columnCount = metaData.getColumnCount(); // 获取表中列的个数
				for (int i = 1; i <= columnCount; i++) {
					// 获取列名
					String columnName = metaData.getColumnName(i);
					// 列名对应的值
					Object value = rs.getObject(columnName);
					// 把列名---值
					map.put(columnName, value);
				}

				// map---》转换成对象
				obj = mapToJavaBean(map);
			}
		}
		return obj;
	}

	private <T> T mapToJavaBean(Map<String, Object> map) {
		T obj = null;
		try {
			// 创建一个T对象
			obj = (T) type.newInstance();
			// 获取这个类的属性名
			Field[] fs = type.getDeclaredFields();
			for (Field f : fs) {
				System.out.println("Hero类中的属性:" + f.getName() + "," + f.getType());
				f.setAccessible(true); // 暴力访问
				// 反射操作
				if (f.getType() == int.class) {
					f.set(obj, (Integer) map.get(f.getName()));
				}
				if (f.getType() == String.class) {
					f.set(obj, (String) map.get(f.getName()));
				}
				if (f.getType() == java.util.Date.class) {
					f.set(obj, (java.sql.Date) map.get(f.getName()));
				}
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return obj;
	}

}

模拟QueryRunner类:

package com.pojo.DataBaseConn;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.sql.DataSource;

import org.apache.commons.dbutils.ResultSetHandler;


public class QueryRunner {

	private DataSource dataSource;

	public QueryRunner(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	/**
	   *    通用的插入,修改,删除的方法
	 * @param sql
	 * @param params
	 * @return
	 * @throws SQLException
	 */
	public int update(String sql,Object... params)throws SQLException{
		//1.从连接池中获取连接
		Connection conn=dataSource.getConnection();
		//2.创建预编译处理对象
		PreparedStatement ps=conn.prepareStatement(sql);
		//3.给sql语句中的问号赋值
		if(params!=null && params.length>0) {
			 for(int i=0;i<params.length;i++) {
				 ps.setObject(i+1, params[i]);
			 }
		}
		//4,执行sql语句
		int n=ps.executeUpdate();
		return n;
	}

	/**
	 * 
	 * @param <T> 泛型方法
	 * @param sql  指向select语句
	 * @param rsh   处理结果集的接口,handle方法,将结果集转换成T类型
	 * @param params sql语句?参数的值
	 * @return  转换后的对象
	 * @throws SQLException
	 */
	public <T> T query(String sql, ResultSetHandler<T> rsh,Object... params) throws SQLException {
		//1.获取连接对象
		Connection conn=dataSource.getConnection();
		//2.创建预编译处理对象
		PreparedStatement ps=conn.prepareStatement(sql);
		//3,若sql语句有问号,则给问号赋值
		if(params!=null && params.length>0) {
			 for(int i=0;i<params.length;i++) {
				 ps.setObject(i+1, params[i]);
			 }
		}
		//4.执行sql语句
		ResultSet rs=ps.executeQuery();
		//5.调用处理器的方法,将结果集转换成T类型
		T obj=rsh.handle(rs);
        return obj ;
    }
}

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值