手写java连接池高级版(动态代理)

手写java连接池高级版(动态代理)

  1. 首先要明白所有连接池(数据源)都实现jdk提供的接口,实现这个规范后就可以在spring容器中都可以使用.已经测试过,百万计数据访问没有出问题,动态代理实现.
  2. 如果spring框架中使用,spirng.xml配置如下:
	<!-- 配置jdbcTemplate数据源 -->
	<bean id="dataSource" class="com.oracle.datesource.MyDateSource" init-method="init" destroy-method="close">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"></property>
		<property name="username" value="c##user"></property>
		<property name="password" value="123456"></property>
		<property name="maxSize" value="30"></property>
	</bean>
  1. 使用jdc提供的动态代理,需要实现一个接口,所以我们需要定义一个Connection适配器,代码如下:
package com.oracle.datesource;

import java.sql.Connection;
/**
 * 
 * <p>Title: MyConnection</p>  
 * <p>Description:需要动态代理,jdk的提供的动态代理需要实现继承一个接口 </p>  
 * @author 丁乾文  
 * @date 2019年1月7日
 * @version 1.0
 */
public interface MyConnection extends Connection{
}

  1. 连接池代码如下:
package com.oracle.datesource;

import java.io.PrintWriter;
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.sql.SQLFeatureNotSupportedException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;

import javax.sql.DataSource;
/**
 * 
 * <p>Title: MyDateSource</p>  
 * <p>Description: 数据源,由spring容器设置为单例</p>  
 * @author 丁乾文  
 * @date 2019年1月7日
 * @version 1.0
 */
public class MyDateSource implements DataSource {
	public String driverClassName;
	private String url;
	private String username;
	private String password;
	private Integer maxSize = 100;
	private final static Object obj = "lock";
	/**
	 * 线程安全集合,并发时防止出问题
	 */
	private List<Connection> conns = Collections.synchronizedList(new ArrayList<>());
	public MyDateSource() {
	}
	/**
	 * 连接池初始化方法
	 * <p>Title: init</p>  
	 * <p>Description: </p>
	 */
	public void init() {
		try {
			Class.forName(driverClassName);
		} catch (ClassNotFoundException e) {
		 throw new RuntimeException("驱动未找到");
		}
		for (int i = 0; i < maxSize; i++) {
			try {
				conns.add(DriverManager.getConnection(url, username, password));
			} catch (SQLException e) {
				throw new RuntimeException("连接出错!");
			}
		}
	}
	/**
	 * 
	 * <p>Title: getConnection</p>  
	 * <p>Description: 获取连接的方法</p>  
	 * @return
	 * @throws SQLException  
	 * @see javax.sql.DataSource#getConnection()
	 */
	@Override
	public Connection getConnection() throws SQLException {
		synchronized (obj) {
			/*
			 * 连接被拿完,等待
			 */
			if (conns.size() == 0) {
				try {
					obj.wait();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			Connection proxyConn = null;
			try {
				/*
				 * 拿走一个连接
				 */
				Connection conn = conns.remove(0);
				/*
				 * 动态代理,关闭连接时阻止关闭,连接还回池中
				 */
				proxyConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(),
						MyConnection.class.getInterfaces(), new InvocationHandler() {
							@Override
							public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
								// TODO Auto-generated method stub
								Object obj1 = null;
								if (method.getName().equals("close")) {
									conns.add(conn);
									obj.notifyAll();
								} else {
									obj1 = method.invoke(conn, args);
								}
								return obj1;
							}
						});
			} catch (IndexOutOfBoundsException e) {
				System.out.println("连接超时!");
			} catch (Exception e) {
				e.printStackTrace();
			}
			return proxyConn;
		}

	}
	/**
	 * 
	 * <p>Title: getConnection</p>  
	 * <p>Description: 获取连接的方法</p>  
	 * @param username
	 * @param password
	 * @return
	 * @throws SQLException  
	 * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
	 */
	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		// TODO Auto-generated method stub
		return getConnection();
	}
	/**
	 * 容器销毁时,关闭销毁连接的方法
	 * <p>Title: close</p>  
	 * <p>Description: </p>
	 */
	public void close() {
		for (Connection connection : conns) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		System.gc();
		System.out.println("已关闭所有连接!!");
	}
	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setMaxSize(Integer maxSize) {
		this.maxSize = maxSize;
	}
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void setLogWriter(PrintWriter arg0) throws SQLException {
		// TODO Auto-generated method stub

	}

	@Override
	public void setLoginTimeout(int arg0) throws SQLException {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean isWrapperFor(Class<?> arg0) throws SQLException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public <T> T unwrap(Class<T> arg0) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42756198/article/details/85983711