• 总结代理模式 并根据数据库连接池原理来模拟实现自己的数据库连接池工具类


    代理模式

    需求:对系统中已有的某个类的功能,进行扩展(增强)

         要求:在不修改源码的情况下,对已有的功能进行增强

         

     静态代理

    抽象接口:保证包含增强功能的对象和原有功能的对象,对外提供相同的方法

    目标对象:封装了原有功能

    代理对象:封装了增强功能和原有功能(通过持有一个目标对象的引用实现)

     问题:代码不够灵活,产生大量冗余工作

    动态代理

    动态代理的实现API

    Proxy :

    帮助程员产生代理对象,提供产生代理类和代理对象的静态方法

          InvocationHandler :

    句柄接口,拦截到,所有代理对象调用的方法(所有代理对象调用的方法,都可以被

    InvocationHandler拦截到)

    模拟实现数据库连接池

    数据库的操作:考虑性能问题

    频繁的连接和断开数据,本身很消耗资源(操作数据的性能)

    ---对数据库连接对象,进行池管理(由池中获得资源,用完之后将资源再次放入)

    连接池的具体实现:

    创建一个集合对象,封装nConnection对象

    2 定义获得连接

    3 和归还连接的功能

    实现代码:

     1 public class DBPoolUtils {
     2     private static String driver;
     3     private static String url;
     4     private static String username;
     5     private static String password;
     6     private static int maxconn;//线程池最大的连接数
     7     
     8     //定义一个集合表示线程池
     9     static List<Connection> list=new ArrayList<Connection>();
    10     //类加载的时候就初始化,创建好连接对象
    11     static{
    12         Properties properties=new Properties();
    13         try {
    14             //读取配置文件信息
    15             properties.load(DBPoolUtils.class.getResourceAsStream("mysql.properties"));
    16             driver=properties.getProperty("driver");
    17             url=properties.getProperty("url");
    18             username=properties.getProperty("username");
    19             password=properties.getProperty("password");
    20             maxconn=Integer.parseInt(properties.getProperty("maxconn"));
    21             Class.forName(driver);
    22             /*
    23              * 创建连接对象
    24              * 因为当用户关闭的时候要把线程连接对象还到线程池中,
    25              * 所有拿到的对象与还回来的对象都应该是代理对象。
    26              * 对close()方法进行拦截,把原来断开连接改成将线程连接对象还到连接池
    27              */            
    28             for (int i = 0; i < maxconn; i++) {
    29                 final Connection conn=DriverManager.getConnection(url, username, password);
    30                 //创建代理对象
    31                 Object connProxy=Proxy.newProxyInstance(
    32                         DBPoolUtils.class.getClassLoader(),//自定义类的类加载器
    33                         new Class<?>[]{Connection.class},//实现的接口的class文件数组
    34                         new InvocationHandler() {//匿名内部类实现InvocationHandler
    35                             
    36                             @Override
    37                             public Object invoke(
    38                                     Object proxy,//代理对象
    39                                     Method method,//代理对象实现接口中调用的方法
    40                                     Object[] args//代理对象实现接口中调用的方法中的参数
    41                                     )throws Throwable {
    42                                 //拦截close()方法,将原来的断开连接改为还回连接池,即:将当前的代理对象加到线程池中
    43                                 String methodName=method.getName();
    44                                 if ("close".equals(methodName)) {
    45                                     list.add((Connection) proxy);
    46                                     //唤醒等待的线程
    47                                     synchronized (list) {
    48                                         list.notifyAll();
    49                                     }
    50                                 }
    51                                 //放行:调用原来的对象方法
    52                                 Object obj=method.invoke(conn, args);    
    53                                 return obj;
    54                             }
    55                         });
    56                 //将创建好的代理线程对象加线程池
    57                 list.add((Connection) connProxy);
    58             }
    59         } catch (IOException e) {
    60             e.printStackTrace();
    61         } catch (ClassNotFoundException e) {
    62             e.printStackTrace();
    63         } catch (SQLException e) {
    64             e.printStackTrace();
    65         }        
    66     }
    67     /**
    68      * 对外提供一个连接对象
    69      * @return
    70      */
    71     public static Connection getConnection(){
    72         //当线程池中没有连接对象的时候,让线程等待,而不报异常,等待其他线程返回时再唤醒
    73         synchronized (list) {
    74             if (list.size()==0) {
    75                 try {
    76                     list.wait();
    77                 } catch (InterruptedException e) {
    78                     e.printStackTrace();
    79                 }
    80             }
    81         }        
    82         //每次从线程池中取出第一个线程
    83         Connection conn=list.remove(0);
    84         System.out.println("剩余:"+list.size());
    85         return conn;
    86     }
    87 }
  • 相关阅读:
    使用Angular CLI生成 Angular 5项目
    asp.net core 2.0 web api + Identity Server 4 + angular 5 可运行前后台源码
    依赖反转原则DIP 与使用了Repository模式的asp.net core项目结构
    Git基本命令 -- 别名 + 忽略 + 推送
    Git基本命令 -- 历史
    多线程,论多核时代爱恨情仇
    凛冬将至,用几款特效暖暖身
    HTML5游戏开发引擎,初识CreateJS
    详解设计模式之工厂模式(简单工厂+工厂方法+抽象工厂)
    详解设计模式六大原则
  • 原文地址:https://www.cnblogs.com/bingzhikun/p/4799939.html
Copyright © 2020-2023  润新知