装饰模式就是给一个对象增加一些新的功能,而且是动态的,要求装饰对象和被装饰对象实现同一个接口,装饰对象持有被装饰对象的实例
为什么要有连接池
数据库的连接对象创建工作,比较消耗性能。
如何创建简单的连接池
在内存中开辟一块空间(集合),一开先往池子里面放置 多个连接对象。 后面需要连接的话,直接从池子里面取。不要去自己创建连接了。 使用完毕, 要记得归还连接。确保连接对象能循环利用。
代码实现自定义连接池
import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; import javax.sql.DataSource; /** * 这是一个数据库连接池 * 一开始先往池子里面放10个连接 * * 1. 开始创建10个连接。 * * 2. 来的程序通过getConnection获取连接 * * 3. 用完之后,使用addBack 归还连接。 * * 4. 扩容。 * * * 问题: * * 1. sun公司针对数据库连接池定义的一套规范。 * * 1. 需要额外记住 addBack方法 * * 2. 单例。 * * 3. 无法面向接口编程。 * * UserDao dao = new UserDaoImpl(); * dao.insert(); * * * DataSource dataSource = new MyDataSource(); * * 因为接口里面没有定义addBack方法。 * * 4. 怎么解决? * */ public class MyDataSource implements DataSource { List <Connection> list = new ArrayList<Connection>(); public MyDataSource() { for (int i = 0; i < 10; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } // 该连接池对外公布的获取连接的方法 @Override public Connection getConnection() throws SQLException { //来拿连接的时候,先看看,池子里面还有没有。 if(list.size() == 0 ){ for (int i = 0; i < 5; i++) { Connection conn = JDBCUtil.getConn(); list.add(conn); } } //remove(0) ---> 移除第一个。 移除的是集合中的第一个。 移除的是开始的那个元素 Connection conn = list.remove(0); //在把这个对象抛出去的时候, 对这个对象进行包装。 Connection connection = new ConnectionWrap(conn, list); return connection; } /** * 用完之后,记得归还。 * @param conn */ public void addBack(Connection conn){ list.add(conn); } //---------------------------- @Override public PrintWriter getLogWriter() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setLogWriter(PrintWriter out) throws SQLException { // TODO Auto-generated method stub } @Override public void setLoginTimeout(int seconds) throws SQLException { // TODO Auto-generated method stub } @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 <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Connection getConnection(String username, String password) throws SQLException { // TODO Auto-generated method stub return null; } }
出现的问题:
1. 需要额外记住 addBack方法 2. 单例。 3. 无法面向接口编程。 UserDao dao = new UserDaoImpl(); dao.insert(); DataSource dataSource = new MyDataSource(); 因为接口里面没有定义addBack方法。 4. 怎么解决? 以addBack 为切入点。 ###解决自定义数据库连接池出现的问题。 > 由于多了一个addBack 方法,所以使用这个连接池的地方,需要额外记住这个方法,并且还不能面向接口编程。 > 我们打算修改接口中的那个close方法。 原来的Connection对象的close方法,是真的关闭连接。 > 打算修改这个close方法,以后在调用close, 并不是真的关闭,而是归还连接对象。
如何扩展某一个方法? > 原有的方法逻辑,不是我们想要的。 想修改自己的逻辑 1. 直接改源码 无法实现。 2. 继承,必须得知道这个接口的具体实现是谁。 3. 使用装饰者模式。
我们使用装饰模式
装饰模式其实就是 和 被装饰的类继承一个 接口 ,
然后把装饰类 的构造方法 写成 加入 被装饰类对象然后再在
装饰类中,写上调用对象方法 再添加自己的方法。
public class ConnectionWrap implements Connection{ Connection connection = null; List <Connection> list ; public ConnectionWrap(Connection connection , List <Connection> list) { super(); this.connection = connection; this.list = list; } @Override public void close() throws SQLException { //connection.close(); System.out.println("有人来归还连接对象了。 归还之前,池子里面是:"+list.size()); list.add(connection); System.out.println("有人来归还连接对象了。 归还之后...,池子里面是:"+list.size()); } ......
JDBCUtil
import java.io.FileInputStream; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; public class JDBCUtil { static String driverClass = null; static String url = null; static String name = null; static String password= null; static{ try { //1. 创建一个属性配置对象 Properties properties = new Properties(); InputStream is = new FileInputStream("jdbc.properties"); //使用类加载器,去读取src底下的资源文件。 后面在servlet // InputStream is = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"); //导入输入流。 properties.load(is); //读取属性 driverClass = properties.getProperty("driverClass"); url = properties.getProperty("url"); name = properties.getProperty("name"); password = properties.getProperty("password"); } catch (Exception e) { e.printStackTrace(); } } /** * 获取连接对象 * @return */ public static Connection getConn(){ Connection conn = null; try { Class.forName(driverClass); //静态代码块 ---> 类加载了,就执行。 java.sql.DriverManager.registerDriver(new Driver()); //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); //DriverManager.getConnection("jdbc:mysql://localhost/test?user=monty&password=greatsqldb"); //2. 建立连接 参数一: 协议 + 访问的数据库 , 参数二: 用户名 , 参数三: 密码。 conn = DriverManager.getConnection(url, name, password); } catch (Exception e) { e.printStackTrace(); } return conn; } /** * 释放资源 * @param conn * @param st * @param rs */ public static void release(Connection conn , Statement st , ResultSet rs){ closeRs(rs); closeSt(st); closeConn(conn); } public static void release(Connection conn , Statement st){ closeSt(st); closeConn(conn); } private static void closeRs(ResultSet rs){ try { if(rs != null){ rs.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ rs = null; } } private static void closeSt(Statement st){ try { if(st != null){ st.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ st = null; } } private static void closeConn(Connection conn){ try { if(conn != null){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); }finally{ conn = null; } } }
测试代码:
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import javax.sql.DataSource; import org.junit.Test; public class TestPool { @Test public void testPool(){ Connection conn = null; PreparedStatement ps = null; MyDataSource dataSource = new MyDataSource(); try { conn = dataSource.getConnection(); String sql = "insert into account values (null , 'xilali' , 10)"; ps = conn.prepareStatement(sql); ps.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); }finally { try { ps.close(); } catch (SQLException e) { e.printStackTrace(); } //归还连接 //conn.close(); //dataSource.addBack(conn); JDBCUtil.release(conn, ps); } } }
完整装饰者代码:
import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.NClob; import java.sql.PreparedStatement; import java.sql.SQLClientInfoException; import java.sql.SQLException; import java.sql.SQLWarning; import java.sql.SQLXML; import java.sql.Savepoint; import java.sql.Statement; import java.sql.Struct; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; public class ConnectionWrap implements Connection{ Connection connection = null; List <Connection> list ; public ConnectionWrap(Connection connection , List <Connection> list) { super(); this.connection = connection; this.list = list; } @Override public void close() throws SQLException { //connection.close(); System.out.println("有人来归还连接对象了。 归还之前,池子里面是:"+list.size()); list.add(connection); System.out.println("有人来归还连接对象了。 归还之后...,池子里面是:"+list.size()); } @Override public PreparedStatement prepareStatement(String sql) throws SQLException { return connection.prepareStatement(sql); } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public Statement createStatement() throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql) throws SQLException { // TODO Auto-generated method stub return null; } @Override public String nativeSQL(String sql) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setAutoCommit(boolean autoCommit) throws SQLException { // TODO Auto-generated method stub } @Override public boolean getAutoCommit() throws SQLException { // TODO Auto-generated method stub return false; } @Override public void commit() throws SQLException { // TODO Auto-generated method stub } @Override public void rollback() throws SQLException { // TODO Auto-generated method stub } @Override public boolean isClosed() throws SQLException { // TODO Auto-generated method stub return false; } @Override public DatabaseMetaData getMetaData() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setReadOnly(boolean readOnly) throws SQLException { // TODO Auto-generated method stub } @Override public boolean isReadOnly() throws SQLException { // TODO Auto-generated method stub return false; } @Override public void setCatalog(String catalog) throws SQLException { // TODO Auto-generated method stub } @Override public String getCatalog() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setTransactionIsolation(int level) throws SQLException { // TODO Auto-generated method stub } @Override public int getTransactionIsolation() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public SQLWarning getWarnings() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void clearWarnings() throws SQLException { // TODO Auto-generated method stub } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Map<String, Class<?>> getTypeMap() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setTypeMap(Map<String, Class<?>> map) throws SQLException { // TODO Auto-generated method stub } @Override public void setHoldability(int holdability) throws SQLException { // TODO Auto-generated method stub } @Override public int getHoldability() throws SQLException { // TODO Auto-generated method stub return 0; } @Override public Savepoint setSavepoint() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Savepoint setSavepoint(String name) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void rollback(Savepoint savepoint) throws SQLException { // TODO Auto-generated method stub } @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { // TODO Auto-generated method stub } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { // TODO Auto-generated method stub return null; } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Clob createClob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Blob createBlob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public NClob createNClob() throws SQLException { // TODO Auto-generated method stub return null; } @Override public SQLXML createSQLXML() throws SQLException { // TODO Auto-generated method stub return null; } @Override public boolean isValid(int timeout) throws SQLException { // TODO Auto-generated method stub return false; } @Override public void setClientInfo(String name, String value) throws SQLClientInfoException { // TODO Auto-generated method stub } @Override public void setClientInfo(Properties properties) throws SQLClientInfoException { // TODO Auto-generated method stub } @Override public String getClientInfo(String name) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Properties getClientInfo() throws SQLException { // TODO Auto-generated method stub return null; } @Override public Array createArrayOf(String typeName, Object[] elements) throws SQLException { // TODO Auto-generated method stub return null; } @Override public Struct createStruct(String typeName, Object[] attributes) throws SQLException { // TODO Auto-generated method stub return null; } @Override public void setSchema(String schema) throws SQLException { // TODO Auto-generated method stub } @Override public String getSchema() throws SQLException { // TODO Auto-generated method stub return null; } @Override public void abort(Executor executor) throws SQLException { // TODO Auto-generated method stub } @Override public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException { // TODO Auto-generated method stub } @Override public int getNetworkTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } }
来源:https://www.cnblogs.com/hetaoyuan/p/12509547.html