最近学习了一下代理发现,代理其实一个蛮有用的,主要是用在动态的实现接口中的某一个方法而不去继承这个接口所用的一种技巧,首先是自定义的一个连接池

代码如下

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.util.LinkedList;
/**
* 自定义连接池, 管理连接
* 代码实现:
1. MyPool.java 连接池类,
2. 指定全局参数: 初始化数目、最大连接数、当前连接、 连接池集合
3. 构造函数:循环创建3个连接
4. 写一个创建连接的方法
5. 获取连接
------> 判断: 池中有连接, 直接拿
------> 池中没有连接,
------> 判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,
创建新的连接
6. 释放连接
-------> 连接放回集合中(..)
*
*/
public class TestMyPool {
private int init_count = 3; // 初始化连接数目
private int max_count = 6; // 最大连接数
private int current_count = 0; // 记录当前使用连接数
// 连接池 (存放所有的初始化连接)
private LinkedList<Connection> pool = new LinkedList<Connection>(); //1. 构造函数中,初始化连接放入连接池
public TestMyPool() {
// 初始化连接
for (int i=0; i<init_count; i++){
// 记录当前连接数目
current_count++;
// 创建原始的连接对象
Connection con = createConnection();
// 把连接加入连接池
pool.addLast(con);
}
} //2. 创建一个新的连接的方法
private Connection createConnection(){
try {
Class.forName("com.mysql.jdbc.Driver");
// 原始的目标对象
final Connection con = DriverManager.getConnection("jdbc:mysql:///jdbc_demo", "root", "root"); /**********对con对象代理**************/ // 对con创建其代理对象
Connection proxy = (Connection) Proxy.newProxyInstance( con.getClass().getClassLoader(), // 类加载器
//con.getClass().getInterfaces(), // 当目标对象是一个具体的类的时候
new Class[]{Connection.class}, // 目标对象实现的接口 new InvocationHandler() { // 当调用con对象方法的时候, 自动触发事务处理器
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// 方法返回值
Object result = null;
// 当前执行的方法的方法名
String methodName = method.getName(); // 判断当执行了close方法的时候,把连接放入连接池
if ("close".equals(methodName)) {
System.out.println("begin:当前执行close方法开始!");
// 连接放入连接池 (判断..)
pool.addLast(con);
System.out.println("end: 当前连接已经放入连接池了!");
} else {
// 调用目标对象方法
result = method.invoke(con, args);
}
return result;
}
}
);
return proxy;
} catch (Exception e) {
throw new RuntimeException(e);
}
} //3. 获取连接
public Connection getConnection(){ // 3.1 判断连接池中是否有连接, 如果有连接,就直接从连接池取出
if (pool.size() > 0){
return pool.removeFirst();
} // 3.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建;
if (current_count < max_count) {
// 记录当前使用的连接数
current_count++;
// 创建连接
return createConnection();
} // 3.3 如果当前已经达到最大连接数,抛出异常
throw new RuntimeException("当前连接已经达到最大连接数目 !");
} //4. 释放连接
public void realeaseConnection(Connection con) {
// 4.1 判断: 池的数目如果小于初始化连接,就放入池中
if (pool.size() < init_count){
pool.addLast(con);
} else {
try {
// 4.2 关闭
current_count--;
con.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
} public static void main(String[] args) throws SQLException {
TestMyPool pool = new TestMyPool();
System.out.println("当前连接: " + pool.current_count); // 3 // 使用连接
pool.getConnection();
pool.getConnection();
Connection con4 = pool.getConnection();
Connection con3 = pool.getConnection();
Connection con2 = pool.getConnection();
Connection con1 = pool.getConnection(); // 释放连接, 连接放回连接池
// pool.realeaseConnection(con1);
/*
* 希望:当关闭连接的时候,要把连接放入连接池!【当调用Connection接口的close方法时候,希望触发pool.addLast(con);操作】
* 把连接放入连接池
* 解决1:实现Connection接口,重写close方法
* 解决2:动态代理
*/
con1.close(); // 再获取
pool.getConnection(); System.out.println("连接池:" + pool.pool.size()); // 0
System.out.println("当前连接: " + pool.current_count); // 3
} }

在这里使用代理主要是为了监测Connection 中的close()方法,当然也可以检测Connection中的其他方法,顺便值得一提的是还有Jdbc的两个开源连接数据库的框架可以为连接数据库省去一些代码:例如dbcp和c3p0这两个框架实现代码分别如下,但前提必须将对应的jar包导入

import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test; public class App_Dbcp { public App_Dbcp() {
// TODO Auto-generated constructor stub
} /**
* 硬编码方式
*/
@Test
public void testDbcp()
{
//DBCP中的核心类
BasicDataSource dataSource = new BasicDataSource();
//连接池配置参数,初始化连接参数,最大连接参数,连接的驱动名 dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setUrl("jdbc:sqlserver://localhost:1433;DatabaseName=教学库");
dataSource.setUsername("sa");
dataSource.setPassword("****"); dataSource.setInitialSize(3);//设置初始化连接参数
dataSource.setMaxActive(6);//设置最大连接数
dataSource.setMaxIdle(3000);//设置最大空闲时间
//获取连接
try {
Connection con = dataSource.getConnection();
con.prepareStatement("delete from tb_user where id=3").executeUpdate();
//关闭
con.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(e);
} } @Test
public void testDBCP()
{
/**
* 使用配置方式来获取参数
*/ try
{
Properties props = new Properties(); InputStream in = App_Dbcp.class.getResourceAsStream("/db.properties");
//读取流文件
props.load(in); //根据Props配置文件直接产生数据对象 DataSource dataSource = BasicDataSourceFactory.createDataSource(props); //创建连接对象
Connection con = dataSource.getConnection();
con.prepareStatement("delete from tb_user where id=4").executeUpdate();
con.close();
}catch(Exception e)
{
throw new RuntimeException(e);
}
}
}

c3p0连接池的测试代码

package gz.itcast.b_c3p0;

import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException; import org.junit.Test; import com.mchange.v2.c3p0.ComboPooledDataSource; public class App { public App() {
// TODO Auto-generated constructor stub
} //硬编码方式,使用c3p0连接池来管理连接数目
@Test
public void testCode() throws Exception {
//创建c3p0核心类
ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setDriverClass("com.microsoft.sqlserver.jdbc.SQLServerDriver");
dataSource.setJdbcUrl("jdbc:sqlserver://localhost:1433;DatabaseName=教学库");
dataSource.setUser("sa");
dataSource.setPassword("***");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(3000); Connection con = dataSource.getConnection(); con.prepareStatement("delete from tb_user where id=3").executeUpdate();
con.close();
} //c3p0使用xml配置文件来管理连接方式 @Test
public void testXml() throws Exception
{
//c3p0核心类,在new 一个对象时就会自动的加载c3p0-config.xml文件
ComboPooledDataSource dataSource = new ComboPooledDataSource(); Connection con = dataSource.getConnection();
con.prepareStatement("delete from tb_user where id=2").executeUpdate(); //关闭连接
con.close();
}
}

对应的xml配置文件

<c3p0-config>
<default-config>
<property name="driverClass">com.microsoft.sqlserver.jdbc.SQLServerDriver</property>
<property name="url">jdbc:sqlserver://localhost:1433;DatabaseName=教学库</property>
<property name="username">sa</property>
<property name="password">****</property>
<property name="initialPoolSize">3</property>
<property name="maxPoolSize">6</property>
<property name="maxIdleTime">3000</property>
<!--
<user-overrides user="swaldman">
<property name="debugUnreturnedConnectionStackTraces">true</property>
</user-overrides>
--> </default-config> <!--
<named-config name="dumbTestConfig">
<property name="maxStatements">200</property>
<property name="jdbcUrl">jdbc:test</property>
<user-overrides user="poop">
<property name="maxStatements">300</property>
</user-overrides>
</named-config>
--> </c3p0-config>

最后就到为止了

java通过代理创建Conncection对象与自定义JDBC连接池的更多相关文章

  1. 自定义JDBC链接池

    上篇简单介绍了jdbc链接数据库: 本篇就说一下自定义连接池以及增删改查的测试: 自定义连接池 自定义链接池的原因 JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  ...

  2. JDBC连接池-自定义连接池

    JDBC连接池 java JDBC连接中用到Connection   在每次对数据进行增删查改 都要 开启  .关闭  ,在实例开发项目中 ,浪费了很大的资源 ,以下是之前连接JDBC的案例 pack ...

  3. 自定义一个简单的JDBC连接池

    一.什么是JDBC连接池? 在传统的JDBC连接中,每次获得一个Connection连接都需要加载通过一些繁杂的代码去获取,例如以下代码: public static Connection getCo ...

  4. Java之JDBC连接池

    数据库连接池 连接池的概述 概念:其实就是一个容器(集合),存放数据库连接的容器. 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时, 从容器中获取连接对象,用户访问完之后 ...

  5. Java中JDBC连接池&JDBCTemplate

    数据库连接池 概念:其实就是一个容器(集合),存放数据库连接的容器. 当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归 ...

  6. c3p0数据库连接池 原创: Java之行 Java之行 5月8日 一、连接池概述 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程

    c3p0数据库连接池 原创: Java之行 Java之行 5月8日 一.连接池概述 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 DB连接池HikariCP为什么如此快 原创: D ...

  7. Java反射机制(创建Class对象的三种方式)

    1:SUN提供的反射机制的类: java.lang.Class<T> java.lang.reflect.Constructor<T> java.lang.reflect.Fi ...

  8. 透析Java本质-谁创建了对象,this是什么

    是构造方法创建的对象吗 package com.java.essence_36; import java.util.ArrayList; import java.util.List; /** * Cr ...

  9. Java基础之创建实例化对象的方式

    Java中创建(实例化)对象的五种方式  1.用new语句直接创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3 ...

随机推荐

  1. coco标注信息与labelme标注信息的详解、相互转换及可视化

    引言 在做实例分割或语义分割的时候,我们通常要用labelme进行标注,labelme标注的json文件与coco数据集已经标注好的json文件的格式和内容有差异.如果要用coco数据集的信息,就要对 ...

  2. 2019nc#3

    题号 标题 已通过代码 题解/讨论 通过率 团队的状态 A Graph Games 点击查看 进入讨论 18/292 未通过 B Crazy Binary String 点击查看 1107/3615 ...

  3. 你知道@RequestMapping的name属性有什么用吗?【享学Spring MVC】

    每篇一句 牛逼架构师:把复杂问题简单化,把简单问题搞没 菜逼架构师:把简单问题复杂化 前言 不知这个标题能否勾起你的好奇心和求知欲?在Spring MVC的使用中,若我说@RequestMapping ...

  4. Mac环境IntelliJ IDEA配置JDK提示The selected directory is not a valid home for JDK

    笔者使用mac配置如下: 硬件环境:MacBook Pro 操作系统:MacOS Sierra 10.13.6 开发工具:IntelliJ IDEA 2016.x JDK版本:已有Open JDK 8 ...

  5. Storm 系列(四)—— Storm 集群环境搭建

    一.集群规划 这里搭建一个 3 节点的 Storm 集群:三台主机上均部署 Supervisor 和 LogViewer 服务.同时为了保证高可用,除了在 hadoop001 上部署主 Nimbus ...

  6. ajax交互案例

    数据交互是前端很重要的一部分,静态页是基础,而交互才是网页的精髓.交互又分为人机交互和前后端数据交互,现阶段的互联网下,大部分的网站都要进行前后端数据交互,如何交互呢?交互的流程大概就是前端发送数据给 ...

  7. springboot 定时器 Schdule

    定时器:定时启动任务,执行代码 1.在启动类中加入注解: 2.创建一个类,并且在这个类上加入注解:@Component 3.定义一个方法,在方法上加入注解:@Scheduled(cron=" ...

  8. CSS精灵图合成工具

    链接:http://pan.baidu.com/s/1o7OUUVo 提取密码:rmnx

  9. SWPU CTF题解

    本博客为西南石油大学(南充校区)CTF团队赛的题解 所有题目网址:http://47.106.87.69:9000/game 今天我是流泪狗狗头 解压后发现压缩包中是一个带有密码的图片,winhex分 ...

  10. ansible-playbook流程控制-loops循环使用

    1. ansible-playbook流程控制-loops循环使用    有时你想要多次重复任务.在计算机编程中,这称为循环.common ansible循环包括使用文件模块更改多个文件和/或目录的所 ...