Chinese To English     英文 转 中文             
         
随笔-27  评论-53  文章-0  trackbacks-0

        大家都知道,在实际应用开发中都会用到数据库。要用数据库我们就必须和数据取得连接,否则一切都是空谈,我想这个没有什么好多说的。正因如此问题就出来了,和数据库取得连接是比较耗资源,而一个网站每天的访问量也是惊人的,想一想如果客户端每向服务器发送一个请求服器就要进行打开连接和关闭连接的工作,这样做明显是不合理,在实际开发中如果是这样去实现数据的持久化真是不可思议。所以引入了连接池的概念,所谓连接池就是当用完一个连接后不是将连接直接关闭而是将它放入到一个容器中缓存放起来,下次再用的时候就直接在容器中取,从而初实现连接的重用。

1:连接池实现类

  1package net.vicp.jiasoft.dpcp.connectionpool;
  2
  3import java.sql.Connection;
  4import java.sql.DriverManager;
  5import java.sql.SQLException;
  6import java.util.Vector;
  7import net.vicp.jiasoft.dpcp.dynaproxy.ConnectionProxy;
  8import net.vicp.jiasoft.dpcp.util.PropertiesUtil;
  9
 10/**
 11 * @author Jak.Shen
 12 * 日期:2008-3-31
 13 * 说明:连接池实现类
 14 */

 15
 16public class ConnectionPool {
 17
 18    private static ConnectionPool connectionPool;//自身静态成员变量,用于实现单例.
 19    private static Vector connPool;//连接缓存容器
 20    private int poolMaxSize = 10;//连接池最大缓存数
 21    private String userName;//连接用户名
 22    private String password;//连接密码
 23    private String driverClass;//连接驱动
 24    private String url;//连接字符串
 25
 26    /**
 27     * 私有构造方法,初始化变量.并心预填充连接池。
 28     */

 29    private ConnectionPool() {
 30        String temp = PropertiesUtil.getValueByKey("poolMaxSize");
 31        if (temp != null{
 32            poolMaxSize = Integer.parseInt(temp);
 33        }

 34        userName = PropertiesUtil.getValueByKey("userName");
 35        password = PropertiesUtil.getValueByKey("password");
 36        driverClass = PropertiesUtil.getValueByKey("driverClass");
 37        url = PropertiesUtil.getValueByKey("url");
 38        connPool = new Vector();
 39        int size = 0;
 40        if (poolMaxSize > 5{
 41            size = 5;
 42        }
 else {
 43            size = poolMaxSize;
 44        }

 45        for (int i = 0; i < size; i++{
 46            connPool.add(createConnection());//预填充连接池
 47        }

 48    }

 49
 50    /**
 51     * 此方法用于创建并返回连接池对象。
 52     * @return
 53     */

 54    public static ConnectionPool newInstance() {
 55        if (connectionPool == null{
 56            connectionPool = new ConnectionPool();
 57        }

 58        return connectionPool;
 59    }

 60
 61    /**
 62     * 此方法用于创建一个连接。
 63     * @return
 64     */

 65    private Connection createConnection() {
 66        Connection connection = null;
 67        try {
 68            Class.forName(driverClass);
 69        }
 catch (ClassNotFoundException e) {
 70            e.printStackTrace();
 71        }

 72        try {
 73            connection = DriverManager.getConnection(url, userName, password);
 74        }
 catch (SQLException e) {
 75            e.printStackTrace();
 76        }

 77        return connection;
 78    }

 79
 80    /**
 81     * 此方法用于将用完的连接放入池中。
 82     */

 83    public static synchronized void releaseConnection(Connection connection) {
 84        connPool.add(connection);
 85    }

 86
 87    /**
 88     * 此方法用于返回一个连接。
 89     * @return
 90     */

 91    public synchronized Connection getConnection() {
 92        // 要防止直接关闭连接因此需要对Connection的close()方法进行拦截
 93        // 所以需要要给Connection接口动态加入代理,getConnection()是加入代理的好地方法
 94        // connectionProxy是动态代理对象
 95        ConnectionProxy connectionProxy = new ConnectionProxy();
 96        int size = connPool.size();
 97        if (connPool.size() == 0 || size < poolMaxSize) {
 98            connectionProxy.setConnection(createConnection());
 99            return connectionProxy.proxyBind();
100        }

101        Connection connection = (Connection) connPool.get(size - 1);
102        connectionProxy.setConnection(connection);
103        connPool.remove(size - 1);
104        return connectionProxy.proxyBind();
105    }

106}

107

2:动态代理类
 1package net.vicp.jiasoft.dpcp.dynaproxy;
 2
 3import java.lang.reflect.InvocationHandler;
 4import java.lang.reflect.Method;
 5import java.lang.reflect.Proxy;
 6import java.sql.Connection;
 7import net.vicp.jiasoft.dpcp.connectionpool.ConnectionPool;
 8
 9/** 
10 * @author Jak.Shen
11 * 日期:2008-3-31
12 * 说明:动态代理实类,实现InvocationHandler接口就可以成为动态代理了.要注意的是只能对接口代理。
13 */

14 
15public class ConnectionProxy implements InvocationHandler {
16
17    private Connection connection;//动态代理的对象
18
19    public ConnectionProxy() {
20    }

21
22    public ConnectionProxy(Connection connection) {
23        this.connection = connection;
24    }

25
26    /**
27     * 重写实现InvocationHandler方法invoke()。
28     * 此处注意@Override标注在JDK1.6中才支持,JDK1.6以下版本请将@Override标注去掉。
29     */

30    @Override
31    public Object invoke(Object proxy, Method method, Object[] args)
32            throws Throwable {
33        // 如果方法是close(),就替换成连接池的releaseConnection()方法.
34        if (method.getName().equals("close")) {
35            System.out.println("before invoke !");
36            ConnectionPool.releaseConnection(connection);
37            System.out.println("after invoke !");
38        }
 else {
39            // 对非close()方法,不做处理,直接调用.
40            return method.invoke(connection, args);
41        }

42        return null;
43    }

44
45    /**
46     * 绑定要进行代理的对象
47     * @return
48     */

49    public Connection proxyBind() {
50        // 返回一个指定接口的代理类实例
51        // newProxyInstance() arg0-->定义代理类的类加载器
52        // newProxyInstance() arg1-->代理类要实现的接口列表
53        // newProxyInstance() arg2-->指派方法调用的调用处理程序(此处就是去调用this对象的invoke())
54        Connection proxyConnection = (Connection) Proxy.newProxyInstance(
55                connection.getClass().getClassLoader(), connection.getClass()
56                        .getInterfaces(), this);
57        return proxyConnection;
58    }

59
60    public Connection getConnection() {
61        return connection;
62    }

63
64    public void setConnection(Connection connection) {
65        this.connection = connection;
66    }

67}

68

3:属性文件操作工具类
 1package net.vicp.jiasoft.dpcp.util;
 2
 3import java.io.FileInputStream;
 4import java.io.FileNotFoundException;
 5import java.io.IOException;
 6import java.util.Properties;
 7
 8/** 
 9 * @author Jak.Shen
10 * 日期:2008-3-31
11 * 说明:属性文件操作工具类
12 */

13
14public class PropertiesUtil {
15    private static Properties properties = new Properties();
16    private static FileInputStream fileInputStream;
17
18    /**
19     * 从属性文件中根据Key取值
20     * @param key
21     * @return
22     */

23    public static String getValueByKey(String key) {
24        if (fileInputStream == null{
25            try {
26                fileInputStream = new FileInputStream("src/dpcp.properties");
27            }
 catch (FileNotFoundException e) {
28                e.printStackTrace();
29            }

30        }

31        try {
32            properties.load(fileInputStream);
33        }
 catch (IOException e) {
34            e.printStackTrace();
35        }

36        return properties.get(key).toString();
37    }

38}

39

4:测试客户端
 1package net.vicp.jiasoft.dpcp.client;
 2
 3import java.sql.Connection;
 4import java.sql.SQLException;
 5import net.vicp.jiasoft.dpcp.connectionpool.ConnectionPool;
 6
 7/** 
 8 * @author Jak.Shen
 9 * 日期:2008-3-31
10 * 说明:动态代理连接池测试客户端
11 */

12public class DbPoolClient {
13
14    public static void main(String[] args) {
15        ConnectionPool connectionPool = ConnectionPool.newInstance();
16        Connection connection = connectionPool.getConnection();
17        try {
18            connection.close();
19        }
 catch (SQLException e) {
20            e.printStackTrace();
21        }

22    }

23}

24

5:属性配置文件(dpcp.properties)
 1#最大连接数
 2poolMaxSize=4
 3#连接用户名
 4userName=scott
 5#连接密码
 6password=tiger
 7#连接驱动
 8driverClass=oracle.jdbc.driver.OracleDriver
 9#连接字符串
10url=jdbc:oracle:thin:@localhost:1521:ACCP

源码下载 -- (ConnectionPool.rar)

杰森 
邮箱:json.shen(at)gmail.com
网站:www.shenjia.org
posted on 2008-03-31 18:17 杰森 阅读(2432) 评论(2)  编辑  收藏 所属分类: JavaSE

评论:
# re: Java实现简单动态代理连接池 2008-04-18 10:33 | YangYang
写的很好,学习了。 msn:seeblue1981@hotmail.com  回复  更多评论
  
# re: Java实现简单动态代理连接池 2008-04-18 16:53 | Jak.Shen
@YangYang
多谢支持!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
嗨117