2018-07-24期 Java动态代理实现数据库连接池

package cn.sjq.proxy.ds.pool;

import java.io.PrintWriter;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.SQLFeatureNotSupportedException;

import java.util.LinkedList;

import java.util.logging.Logger;

import javax.sql.DataSource;

/**

* 使用Java 动态代理实现数据库连接池Pool

*

* @author songjq

*

*/

public class DataSourcePool implements DataSource {

// 驱动程序名

static String driver = "com.mysql.jdbc.Driver";

// URL指向要访问的数据库名mydata

static String url = "jdbc:mysql://hadoop-server03:3306/mysql";

// MySQL配置时的用户名

static String user = "root";

// MySQL配置时的密码

static String password = "user#0989";

// 定义一个链表保存20个数据库连接

static LinkedList<Connection> pool = new LinkedList<>();

// 静态代码块

static {

// 加载驱动程序

try {

Class.forName(driver);

for (int i = 0; i < 20; i++) {

pool.add(DriverManager.getConnection(url, user, password));

}

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public PrintWriter getLogWriter() throws SQLException {

// TODO Auto-generated method stub

return null;

}

@Override

public void setLogWriter(PrintWriter out) throws SQLException {

// TODO Auto-generated method stub

}

@Override

public void setLoginTimeout(int seconds) throws SQLException {

// TODO Auto-generated method stub

}

@Override

public int getLoginTimeout() throws SQLException {

// TODO Auto-generated method stub

return 0;

}

@Override

public Logger getParentLogger() throws SQLFeatureNotSupportedException {

// TODO Auto-generated method stub

return null;

}

@Override

public <T> T unwrap(Class<T> iface) throws SQLException {

// TODO Auto-generated method stub

return null;

}

@Override

public boolean isWrapperFor(Class<?> iface) throws SQLException {

// TODO Auto-generated method stub

return false;

}

/**

* 重写getConnection()方法

*/

@Override

public Connection getConnection() throws SQLException {

/*

* 如果pool长度大于0,说明pool存在连接,将第一个对象返回,否则抛出异常

*/

// 未使用动态代理前

/*

* if(pool.size()>0) { return pool.removeFirst(); }else { throw new

* SQLException("连接池已耗尽,无法分配新的连接..."); }

*/

/**

* 未使用动态代理前,客户端进行第21次连接的时候就抛出连接池已耗尽的异常,虽然使用conn.close()方法归还连接,但是该方法是将连接归还给数据库,而不是我们定义的pool对象

* 如果要实现调用conn.close()方法后将conn连接对象归还给pool连接池,就需要使用Java

* 动态代理重写Connection接口的close()方法。

* 这是客户端第19次获得数据库连接...,连接信息:[email protected]

* 这是客户端第20次获得数据库连接...,连接信息:[email protected] Exception in

* thread "main" java.sql.SQLException: 连接池已耗尽,无法分配新的连接... at

* cn.sjq.proxy.ds.pool.DataSourcePool.getConnection(DataSourcePool.java:101) at

* cn.sjq.proxy.ds.pool.ClientTest.main(ClientTest.java:21)

*/

/**

* 下面使用动态代理重写Connection接口的close()方法,实现调用close()方法后归还DataSourcePool连接池的连接。 loader

* - 定义代理类的类加载器 interfaces - 代理类要实现的接口列表 h - 指派方法调用的调用处理程序

* 通过使用动态代理后客户端可以源源不断获得连接,而不是到达20个上限后抛出异常,如下:

* 这是客户端第25次获得数据库连接...,连接信息:[email protected]

* 这是客户端第26次获得数据库连接...,连接信息:[email protected]

* 这是客户端第27次获得数据库连接...,连接信息:c[email protected]

* 这是客户端第28次获得数据库连接...,连接信息:[email protected]

*/

if (pool.size() > 0) {

// 从pool里面获取一个连接对象Connection

final Connection conn = pool.removeFirst();

// 使用Java 动态代理重写Connection中close()方法

Connection newProxyConn = (Connection) Proxy.newProxyInstance(DataSourcePool.class.getClassLoader(),

conn.getClass().getInterfaces(), new InvocationHandler() {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

// 重写close方法

if (method.getName().equals("close")) {

// 回收释放连接

pool.add(conn);

return null;

} else {

// 其它方法不重写

return method.invoke(conn, args);

}

}

});

return newProxyConn;

} else {

throw new SQLException("连接池已耗尽,无法分配新的连接...");

}

}

@Override

public Connection getConnection(String username, String password) throws SQLException {

// TODO Auto-generated method stub

return null;

}

}

package cn.sjq.proxy.ds.pool;

import java.sql.Connection;

import java.sql.SQLException;

/**

* 模拟客户端连接数据

* @author songjq

*

*/

public class ClientTest {

public static void main(String[] args) throws SQLException, InterruptedException {

int count = 0;

//实例化连接池对象DataSourcePool

DataSourcePool pool = new DataSourcePool();

//循环模拟连接数据库

while(true) {

//获得一个连接

Connection conn = pool.getConnection();

count++;

//打印连接信息

System.out.println("这是客户端第"+count+"次获得数据库连接...,连接信息:"+conn);

//关闭客户端连接,将连接归还连接池

conn.close();

//线程睡眠3秒

Thread.sleep(3000);

}

}

}

原文地址:http://blog.51cto.com/2951890/2149343

时间: 2024-08-24 03:36:54

2018-07-24期 Java动态代理实现数据库连接池的相关文章

使用Java中的动态代理实现数据库连接池

2002 年 12 月 05 日 作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池. 数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈.我们可以在 互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度.很多的连接池 都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前

java动态代理之CGLIB实现

动态代理(CGlib 与连接池的案例) Cglib代理: 针对类来实现代理,对指定目标 产生一个子类 通过方法拦截技术拦截所有父类方法的调用. 我们要使用cglib代理必须引入 cglib的jar包 <dependencies> <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId&g

好程序员Java教程Java动态代理机制详解

好程序员Java教程Java动态代理机制详解:在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的.首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler: 1InvocationHandler is the interface implemented by the invocation handle

Java动态代理简单应用

概念 代理模式是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象.这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色. Java动态代理比代理的思想更进一步,因为它可以动态地创建代理并动态地处理对代理方法的调用.在动态代理上所做的所有调用都会被重定向到单一的调用处理器(InvocationHandler)上,调用处理器的工作是揭示调用的类型并确定相应的策略. Java动态代理实现机制采用了反射的思想,有关于反射的基础知识,可以参见博客

Java 动态代理机制分析及扩展

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅读本文,读者将会对 Java 动态代理机制有更加深入的理解.本文首先从 Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现. 代理:设计模式 代理是一种常用的设计模式,其

深入理解java动态代理的实现机制

今天将从以下5方面来系统的学习一下java动态代理的实现机制: 什么是代理 什么是静态代理 什么是动态代理 动态代理的实现机制 动态代理的使用场景 1,什么是代理 相信大家都有购买过火车票或者机票的经历,有的人在携程买,有的在飞猪,也有的在微信上买等等,这里的携程飞猪微信也好都是受铁路部的委托代理售卖火车票,这里的携程飞猪就是代理类,铁路部就是委托类,这就是代理 2,什么是静态代理 所谓的静态代理就是在代码运行之前,代理类就已经存在,通常情况下, 静态代理中的代理类和委托类会实现同一接口或是派生

JAVA 动态代理原理和实现

在 Java 中动态代理和代理都很常见,几乎是所有主流框架都用到过的知识.在面试中也是经常被提到的话题,于是便总结了本文. Java动态代理的基本原理为:被代理对象需要实现某个接口(这是前提),代理对象会拦截对被代理对象的方法调用,在其中可以全然抛弃被代理对象的方法实现而完成另外的功能,也可以在被代理对象方法调用的前后增加一些额外的功能. 动态代理可以为其他对象提供一个代理以控制对某个对象的访问. 代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. JDK

Java动态代理实现方式一

Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理 实现方式一:静态代理 静态代理方式的优点 静态代理方式的缺点 Java动态代理实现方式一:InvocationHandler Java动态代理实现方式二:CGLIB 用CGLIB实现Java动态代理的局限性 面试问题:Java里的代理设计模式(Proxy Design Pattern)一共有几种实现方式?这个题目很像孔乙己问“茴香豆的茴字有哪几种写法? 所谓代理模式,是指客户端(Client)并不直接调用实际的对象(下图右下角

理解java动态代理

java动态代理是java语言的一项高级特性.在平时的项目开发中,可能很难遇到动态代理的案例.但是动态代理在很多框架中起着不可替代的作用,例如Spring的AOP.今天我们就聊一聊java动态代理的实现原理. jdk对于动态代理的支持主要依赖于两个类:Proxy和InvocationHandler.我们先看一下类图. Subject类是主题类,定义了我要做什么.我们需要代理的类即实现Subject接口的RealSubject. 1.InvocationHandler InvocationHand