自建连接池,通过动态代理增强getConnection()方法,使其调用用close()方法时具有返回连接的功能
文章目录
- 一、JDBC
- 1.概述与原理
- 2.API介绍
- 二、连接池
- 三、动态代理
- 1.概述与原理
- 2.API介绍
- 四、动态代理增强getConnection()方法
- 1.原因
- 2.代码思路与实现
- 3.测试
一、JDBC
1.概述与原理
JDBC(Java DataBase Connectivity):就是Java数据库连接,简单说就是封装了java语言操作不同据库(例如:mysql,oracle、sqlServer等数据库)的接口,各个数据库厂商实现这个接口。因此java语言可以通过JDBC操作各个数据库。
JDBC工作原理
sun公司为了简化和统一java连接数据库,定义的一套规范(类,接口),并提供连接数据库的协议标准
2.API介绍
1. DriverManager:驱动管理器
+ 注册驱动:public static void registerDriver(Driver driver);
+ 获得连接: public static Connection getConnection(String url,String user,String password);
2. Connection: 代表连接对象
+ 创建执行sql语句对象:public Statement createStatement();
+ 创建预编译sql语句对象:PreparedStatement prepareStatement(String sql);
+ 事务操作:
+ void setAutoCommit(boolean autoCommit); false--手动开启事务(start transaction)
+ void commit();提交事务(commit)
+ void rollback();回滚事务(rollback)
3. Statement: 执行sql语句对象
+ 执行查询 ResultSet executeQuery(String sql); 返回结果集
+ 执行增删改 int excuteUpdate(String sql); 返回受影响的行数
4. ResultSet: 结果集
+ boolen next(); 每调用一次, 光标就向下移动一行; 这个行有数据, 返回true; 没有数据, 返回false
+ get类型(String 列名); 根据列名 获得当前列的数据
二、连接池
1.概述与原理
为什么要使用连接池:
Connection对象在JDBC使用的时候就会去创建一个对象,使用结束以后就会将这个对象给销毁了(close).每次创建和销毁对象都是耗时操作.需要使用连接池对其进行优化.
程序初始化的时候,**初始化多个连接,将多个连接放入到池(集合)中**.每次获取的时候,都可以直接**从连接池中进行获取.使用结束以后,将连接归还到池中.**
连接池原理:
1. 程序一开始就创建一定数量的连接,放在一个容器(集合)中,这个容器称为连接池。
2. 使用的时候直接从连接池中取一个已经创建好的连接对象, 使用完成之后 归还到池子
3. 如果池子里面的连接使用完了, 还有程序需要使用连接, 先等待一段时间(eg: 3s), 如果在这段时间之内有连接归还, 就拿去使用; 如果还没有连接归还, 新创建一个, 但是新创建的这一个不会归还了(销毁)
4. 集合选择LinkedList
增删比较快
LinkedList里面的removeFirst()和addLast()方法和连接池的原理吻合
三、动态代理
1.概述与原理
1.Java.lang.reflect.Proxy:java中负责为实现指定接口的类对象,可以为任意的接口实现类对象做代理。
2.动态代理可以为被代理对象的所有接口的所有方法做代理,动态代理可以在不改变方法源码的情况下,实现对方法功能的增强,而不需要专门定义一个代理类。
3.动态代理与代理模式原理是一样,只是没有具体的代理类,底层通过反射机制生成代理对象,无需程序员手工编写它的源代码。
4.动态代理的获取:jdk提供一个Proxy类,为实现指定接口的对象直接生成代理对象
5.动态代理同时也提高了开发效率。
缺点:只能针对接口的实现类做代理对象,普通类是不能做代理对象的。
2.API介绍
四、动态代理增强getConnection()方法
1.原因:
自建连接池为什么要去增强getConnection()方法,当连接释放资源时调用的是Connection接口中的close()方法,而我们的连接是通过DataSource接口中的getConnection()方法获取,其中并没有close()方法且关闭后没有返回连接的功能。要使我们通过自建的连接池获得的连接具有关闭资源的方法且关闭之后要返回连接,就需要通过动态代理模式增强getConnection()方法返回增强的连接,该增强的连接实现了Connection接口具有close()方法 通过pool.addLast(connection)归还连接
2.代码思路与实现
自定义MyDataSource连接池类实现DataSouce接口(为了增强getConnection方法)
定义Linkedlist集合存储连接,因为LinkedList增删比较快且LinkedList里面的removeFirst()和addLast()方法和连接池的原理吻合,使用public static修饰。
在静态代码块中创建连接池
通过读取Properties对象读取properties文件得到创建驱动和获取连接的参数
// 创建Properties对象Properties pro = new Properties();// 加载配置文件// 通过类加载器返回的流默认路径是srcInputStream is = MyDataSource.class.getClassLoader().getResourceAsStream("me.properties");pro.load(is);// 获取配置文件中的数据mydriverclass = pro.getProperty("mydriverclass");url = pro.getProperty("url");username = pro.getProperty("username");password = pro.getProperty("password");// 注册驱动Class.forName(mydriverclass);
注册驱动
循环创建connection对象加入list集合
通过动态代理对getConnection()方法增强,判断是否是增强的方法是则归还连接,不是则通过反射机制调用方法。
整体代码如下
public class MyDataSource implements DataSource {//- 在连接池类中,定义一个LinkedList集合成员变量(表示连接池)private static LinkedList<Connection> pool = new LinkedList<>();//- 在连接池类的静态代码块中,创建固定数量个连接,并存储到LinkedList集合中static {String username = null;String password = null;String url = null;String mydriverclass = null;try {// 创建Properties对象Properties pro = new Properties();// 加载配置文件// 通过类加载器返回的流默认路径是srcInputStream is = MyDataSource.class.getClassLoader().getResourceAsStream("me.properties");pro.load(is);// 获取配置文件中的数据mydriverclass = pro.getProperty("mydriverclass");url = pro.getProperty("url");username = pro.getProperty("username");password = pro.getProperty("password");// 注册驱动Class.forName(mydriverclass);} catch (Exception e) {e.printStackTrace();}for (int i = 0; i < 5; i++) {try {// 创建连接Connection connection = DriverManager.getConnection(url, username, password);// 把连接添加到连接池中pool.add(connection);} catch (Exception e) {e.printStackTrace();}}}@Overridepublic Connection getConnection() throws SQLException {//- 在连接池类中定义一个公共的非静态的成员方法,用来获取连接(删除集合中第一个元素)// 被代理对象----没有增强的连接对象Connection connection = pool.removeFirst();// 代理对象----增强后的连接对象// 获取被代理类的类加载器ClassLoader classLoader = connection.getClass().getClassLoader();// 获取被代理类实现的所有接口的字节码对象Class<?>[] interfaces = connection.getClass().getInterfaces();// 创建事件处理接口InvocationHandler h = new InvocationHandler() {@Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {// 判断是否是增强的方法if ("close".equals(method.getName())) {// 增强---归还连接pool.addLast(connection);return null;} else {// 不增强---通过反射调用被代理类中同名的方法Object res = method.invoke(connection, objects);return res;}}};// 直接生成代理对象Connection proxy = (Connection) Proxy.newProxyInstance(classLoader, interfaces, h);// 返回代理对象return proxy;}//- 在连接池类中定义一个公共的非静态方法用来获取连接池中的连接数量public int size() {return pool.size();}@Overridepublic Connection getConnection(String s, String s1) throws SQLException {return null;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter printWriter) throws SQLException {}@Overridepublic void setLoginTimeout(int i) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}@Overridepublic <T> T unwrap(Class<T> aClass) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> aClass) throws SQLException {return false;}
}
3测试
public class Test {public static void main(String[] args) throws Exception{MyDataSource myDataSource = new MyDataSource();Connection connection = myDataSource.getConnection();String sql="select * from user where id = ?";PreparedStatement ps = connection.prepareStatement(sql);ps.setInt(1,1);ResultSet resultSet = ps.executeQuery();User user=null;while(resultSet.next()){int id = resultSet.getInt("id");String username = resultSet.getString("username");String password = resultSet.getString("password");String nickname = resultSet.getString("nickname");user=new User(id,username,password,nickname);}System.out.println("连接池中连接的数量:"+myDataSource.size());// 4System.out.println("user:" + user);//- 释放资源resultSet.close();ps.close();connection.close();// 销毁变成归还//dataSource.addBack(connection);System.out.println("连接池中连接的数量:"+myDataSource.size());// 5}
}
运行结果
用完之后释放了资源且归还了连接。
自建连接池,通过动态代理增强getConnection()方法,使其调用用close()方法时具有返回连接的功能相关推荐
- 修改 连接层_Mybatis连接池_动态sql语句_多表查询实现
Mybatis连接池 Mybatis中的连接池Mybatis连接池提供了3种方式的配置:配置的位置:主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种 ...
- 一顿饭的时间,教你怎样快速使用 动态代理ip 做一个获取Steam 热销商品 的方法
- Java Web ConnectionPool (连接池技术)
根目录下: dbpool.properties 代码: driverClassName=oracle.jdbc.driver.OracleDriverusername=scottpassword=ti ...
- mybatis学习(四)连接池、事务、动态SQL、多表查询
目录 连接池 事务 动态SQL 1.if标签 2.where标签 3.foreach标签 4.sql标签 多表操作 (一)一对多.多对一 .一对一 1.查询所有账户,在账户信息后显示所属的用户的用户名 ...
- 使用 JAVA 中的动态代理实现数据库连接池
数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈.我们可以在互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共 ...
- java类加载机制、反射、动态代理详解
类的加载.连接和初始化(系统可能在第一次使用某个类时加载该类, 也可能采用预加载机制来加载某个类)动态代理实现 1.JVM和类 当调用 java 命令运行某个 Java 程序时, 该命令将会启动一个 ...
- Java静态代理、动态代理与CGLib代理
java的动态代理举足轻重,它同反射原理一直是许多框架的底层实现.今天唠一下. 一.代理模式 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修改原目标 ...
- 14-数据库连接池和jdbc优化
一.数据库连接池 1. 什么是连接池 传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的连接,完成数据查询后会关闭数据库的链接. 这样的方式会导致用户每次请求 ...
- mybatis里的日志动态代理
上一篇博客说到mybatis对日志的实现有一个优先顺序,本篇以jdkLog为例探讨mybatis运用到的动态代理模式. 首先要知道它为什么要使用动态代理,可以观察到当执行mybatis的代码时,他总能 ...
最新文章
- python【蓝桥杯vip练习题库】BASIC-28Huffuman树(贪心 Huffuman)
- 752. Open the Lock
- [转] 三种Python下载url并保存文件的代码
- 黑马程序员 C语言:循环语句
- [Chatter] 看小说「数字风暴」有感
- 私钥、公钥、数字签名、数字证书、HTTPS
- BZOJ P1059 [ZJOI2007]矩阵游戏——solution
- Ps 初学者教程,如何在图片中创建新背景?
- JAVA中读取配置文件以及修改配置文件
- 这才是真相,“轻点,疼”被禁却另有玄机
- 【4】基于深度神经网络的脑电睡眠分期方法研究(训练模型)
- Briss-最好用的pdf裁边工具
- 0xc000007b的解决办法(续)
- 设置此计算机的用户已选择屏蔽此网站,已阻止此网站显示有安全证书错误的内容,详细教您已阻止此网站显示有安全证书错误的内容怎么解决...
- python中正则表达式与jieba分词的使用
- python opencv 二维码定位识别
- 支持串口上传图片和数据到服务器的4G低功耗摄像头方案
- MDC是什么鬼?用法、源码一锅端
- 设计模式(模板模式,命令模式,备忘录模式)
- 雁门关下英雄泪——看97版《天龙八部》有感