【Java EE 学习第15天】【自定义数据库连接池之动态代理的使用】

一、动态代理的作用

  使用动态代理可以拦截一个对象某个方法的执行,并执行自定义的方法,其本质是反射

  优点:灵活

  缺点:由于其本质是反射,所以执行速度相对要慢一些

二、数据库连接池设计思想

  1.为什么要使用数据库连接池:创建Connection对象的过程是非常耗时的,为了保证Connection可以重用,应该对Connection进行管理。

  2.设计要求:

    (1)连接池能够实现维护多个连接,必须要保证每一个线程获取到的是不同的Connection对象。

    (2)提供一个方法能够回收连接。

  3.最基本的实现

package day15_2;

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

/**
 * 使用最基本的方式创建数据库连接池
 * @author kdyzm
 *
 */
public class JDBCPool1 {
    private static ArrayList<Connection>pool=new ArrayList<Connection>();
    static
    {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url="jdbc:mysq://localhost:3306?useUnicode=true&characterEncoding=utf-8";
            for(int i=0;i<5;i++)
            {
                Connection conn=DriverManager.getConnection(url, "root", "5a6f38");
                pool.add(conn);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Connection getConn()
    {
        synchronized (pool) {
            Connection conn=pool.remove(0);
            System.out.println("还有 "+pool.size()+"个连接");
            return conn;
        }
    }

    public static void back(Connection conn)
    {
        System.out.println("还连接:"+conn);
        pool.add(conn);
    }
}

  4.程序员写代码总是习惯性的调用close方法,如果实际调用了close方法,则该连接将会被释放,再也回收不回来了,所以应当使用一种方法拦截close方法的执行,并且替换成自定义的动作。使用代理可以完成这个任务。

  代码示例:

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.LinkedList;
import java.util.Properties;
public class ConnUtils {
    private static LinkedList<Connection> pool = new LinkedList<Connection>();
    static{
        try {
            //声明资源器类 - 
            Properties prop = new Properties();
            //获取这个文件的路径
            URL url = ConnUtils.class.getClassLoader().getResource("jdbc.properties");
            String path = url.getPath();
            //为了防止有中文或是空格
            path = URLDecoder.decode(path,"UTf-8");
            File file = new File(path);
            //加载jdbc.properties这个文件
            prop.load(new FileInputStream(file));
            //获取信息
            String driver = prop.getProperty("driver");
            Class.forName(driver);
            String jdbcurl = prop.getProperty("url");
            String nm = prop.getProperty("name");
            String pwd = prop.getProperty("pwd");
            //创建三个原生的连接,都将它们代理
            String poolSize = prop.getProperty("poolSize");
            int size = Integer.parseInt(poolSize);
            for(int i=0;i<size;i++){
                final Connection con = DriverManager.getConnection(jdbcurl,nm,pwd);
                //对con进行动态代理
                Object proxyedObj =
                        Proxy.newProxyInstance(ConnUtils.class.getClassLoader(),
                                    new Class[]{Connection.class},
                                    new InvocationHandler() {
                                        public Object invoke(Object proxy, Method method, Object[] args)
                                                throws Throwable {
                                            //是否是close方法
                                            if(method.getName().equals("close")){
                                                synchronized (pool) {
                                                    pool.addLast((Connection) proxy);
                                                    pool.notify();
                                                }
                                                return null;//如果调用的是close则不会调用被代理类的方法。
                                            }
                                            return method.invoke(con, args);
                                        }
                                    });
                //将代理对象放到pool中
                pool.add((Connection) proxyedObj);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConn(){
        synchronized (pool) {
            if(pool.size()==0){  //如果连接池中没有连接则进入等待池中等待
                try {
                    pool.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return getConn();
            }else{          //如果连接池中有连接则将连接分配出去。
                Connection con = pool.removeFirst();
                System.err.println("还有几个:"+pool.size());
                return con;
            }
        }
    }
}

  5.动态代理的核心类。

  (1)Proxy类:提供用于创建动态代理类和实例的动态方法,它还是由这些方法创建的所有动态代理类的超类。

  (2)InvocationHandler接口:是代理实例的调用处理程序实现的接口。

  6.代理的任务

  (1)在内存中创建某个接口的子类。

  (2)拦截所有在代理上执行的方法。

三、联系人管理小练习。

  源代码:https://github.com/kdyzm/day15

  

时间: 2024-11-01 00:45:16

【Java EE 学习第15天】【自定义数据库连接池之动态代理的使用】的相关文章

[javaEE] 数据库连接池和动态代理

实现javax.sql.DataSource接口 实现Connection getConnection()方法 定义一个静态的成员属性LinkedList类型作为连接池,在静态代码块中初始化5条数据库连接,添加到连接池中,在getConnection方法中,当获取连接的时候在连接池中remove掉一条连接就可以了 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lan

【Java EE 学习第16天】【dbcp数据库连接池】【c3p0数据库连接池】

零.回顾之前使用的动态代理的方式实现的数据库连接池: 代码: 1 package day16.utils; 2 3 import java.io.IOException; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.sql.Connection; 8 import java.sql.D

Java EE学习--Quartz基本用法

新浪博客完全不适合写技术类文章.本来是想找一个技术性的博客发发自己最近学的东西,发现博客园起源于咱江苏,一个非常质朴的网站,行,咱要养成好习惯,以后没事多总结总结经验吧.很多时候都在网上搜索别人的总结,我自己也总结些东西,或许多多少少能帮得上别人. 首先提到的是Quartz,一个开源的定期执行计划任务的框架.其实我内心好奇这个框架很久了,像那些能定时修改数据库数据,定时分配任务的功能一直觉得很神奇.心动不如行动,今天我就小小的学习了一下用法,力求言简意赅,大家都懂的我就不说了. 第一步:下载Qu

Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库

参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Java EE 学习(6):IDEA + maven + spring 搭建 web(2) 5 数据库配置 下面,就要通过一个简单的例子,来介绍 SpringMVC 如何集成 Spring Data JPA(由 Hibernate JPA 提供),来进行强大的数据库访问,并通过本章节

Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理

转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库 记录: 通过对用户表的管理,更加深入地讲解SpringMVC的操作. 6 用户管理 既然我们

【Java EE 学习第16天】【dbutils的使用方法】

一.为什么要使用dbutils 使用dbutils可以极大程度的简化代码书写,使得开发进度更快,效率更高 二.dbutils下载地址 http://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi 出现的ds为数据源对象,可以是某个数据库连接池的DataSource,也可以是自定义数据库连接池的DataSource,这里我是用了dbcp数据库连接池. 1 package day16.regular.utils; 2 3

Java EE学习——Quartz的Cron表达式

经历过低谷后,还是要好好学习,越失落会越来越落后. 今天写一下Cron表达式的用法,虽然是之前自己写的,也过了挺长一段时间,这次就拿出来作为回顾吧. Cron表达式是Quartz的精髓(个人觉得),比如我们想设定淘宝“秒杀”的那一秒时间,完全可以用下面的方法设置执行时间. Calendar cal = Calendar.getInstance(); //设置将要发生的时间... cal.set(Calendar.DATE, xxx); //.......常规的生成scheduler和job //

JAVA EE 学习笔记[V1 jsp编程]

在三月初学校开设了javaee的课程,也就此展开了对javaee基础的学习.然后老师也对这次的课程有一定要求.前面的基础就为最终的作业做准备啦~ 在上学期我们学习了java相关知识,也对java se 的安装使用有了一定的认知,而java ee则是构建于java se 平台之上的一套多层的,可扩展的的网络应用. 学习java ee我们首先进行环境的搭建.无非就是使用 tomcat进行服务器的搭建和jdk环境变量配置.而IDE这方面我们选择myeclipse 2016 CI(这个编译器自带tomc

Java EE 学习(5):IDEA + maven + spring 搭建 web(1)

参考:http://www.cnblogs.com/lonelyxmas/p/5397422.html http://www.ctolib.com/docs-IntelliJ-IDEA-c--159047.html 孔老师的<SpringMVC视频教程> 记录: 本节主要完成 使用 maven 管理 spring + 项目 包,搭建 maven+spring 的 web 项目平台. 前提: 已安装并配置好 - Intellij IDEA 16.3.5 Ultimate - JDK 1.8.0_