java之使用动态代理实现数据库连接的回收
1.编写一个管理数据库连接类
1 package cn.mycast.bank.db; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 import java.util.LinkedList; 6 import cn.mycast.bank.util.JdbcUtil; 7 public class MyDatabasePool { 8 LinkedList<Connection> connPool=new LinkedList<Connection>();//存放连接 9 private int Maxsize=10; 10 private int Initsize=6; 11 int Currentsize=0; 12 public MyDatabasePool(){ 13 for(int i=0;i<Initsize;i++)//连接池中存放10个连接 14 { 15 this.connPool.addLast(this.CreateConnection());//每次添加到集合最后面 16 this.Currentsize++; 17 } 18 } 19 public Connection CreateConnection(){//获得连接 20 Connection realconn=JdbcUtil.getConnection(); 21 MyDatabaseHandler handler=new MyDatabaseHandler(this);//代理类 22 return handler.bind(realconn); 23 } 24 public Connection GetConnection() throws SQLException{ 25 synchronized(connPool){ 26 if(this.connPool.size()>0){ 27 return connPool.removeFirst();//取出最上面的一个连接 28 } 29 if(this.Currentsize<Maxsize){ 30 this.Currentsize++; 31 return this.CreateConnection(); 32 } 33 throw new SQLException(""); 34 } 35 } 36 public void FreeConnection(Connection conn){//将用完后的连接放回到集合中 37 this.connPool.addLast(conn); 38 } 39 }
2.编写一个代理类,这里主要是实现一个InvocationHandler的接口
1 package cn.mycast.bank.db; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 import java.lang.reflect.Proxy; 6 import java.sql.Connection; 7 public class MyDatabaseHandler implements InvocationHandler{ 8 private Connection realConnection; 9 private Connection WrapperConn; 10 private MyDatabasePool databasesource; 11 private int Maxsize=10; 12 int Currentsize=0; 13 public MyDatabaseHandler(MyDatabasePool databasesource){ 14 this.databasesource=databasesource; 15 } 16 /* 17 * Proxy类动态根据这里我们制定的接口生成一个class byte,然后通过classloader将class byte生成一个类对象,再将该对象委派给当前代理类的实例 18 */ 19 Connection bind(Connection realConn){ 20 this.realConnection=realConn;//需要代理的原始的对象 21 this.WrapperConn=(Connection)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Connection.class}, this); 22 return WrapperConn; 23 //这步是创建代理对象了,第一个参数指定类加载器:使得这个代理类能访问被代理对象, 24 //第二个参数指定代理类应该具有哪些接口:要不然怎么去代理被代理对象, 25 //第二个参数就是指定,代理对象额外完成的业务逻辑了:如前面所述的获取被代理类的执行时间。 26 } 27 @Override 28 public Object invoke(Object proxy, Method method, Object[] args) 29 throws Throwable { 30 if("close".equals(method.getName())){//这里代理原始类的close方法 31 this.Currentsize++; 32 if(this.Currentsize<this.Maxsize){ 33 this.databasesource.connPool.addLast(this.WrapperConn); 34 }else{ 35 this.realConnection.close(); 36 this.databasesource.Currentsize--; 37 } 38 } 39 return method.invoke(this.realConnection, args); 40 } 41 42 }
3.编写一个测试类
1 package cn.mycast.bank.db; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 6 public class Main { 7 /** 8 * @param args 9 * @throws SQLException 10 */ 11 public static void main(String[] args) { 12 System.out.println("创建连接.........."); 13 MyDatabasePool databasepool=new MyDatabasePool(); 14 15 System.out.println("客户端连接.........."); 16 Connection conn=null; 17 try { 18 conn=databasepool.GetConnection(); 19 System.out.println("連接池中的連接個數"+databasepool.connPool.size()); 20 } catch (SQLException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 }finally{ 24 if(conn!=null){ 25 try { 26 conn.close(); 27 System.out.println("客户端關閉連接.........."); 28 } catch (SQLException e) { 29 e.printStackTrace(); 30 } 31 } 32 } 33 System.out.println("連接池中的連接個數"+databasepool.connPool.size()); 34 } 35 36 }
创建连接..........
客户端连接..........
連接池中的連接個數5
客户端關閉連接..........
連接池中的連接個數6
动态代理工作原理图如下:
动态代理就是对被代理的类进行一次封装包裹,以便加上我们自己需要加的一些业务逻辑。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。