Java編寫準備數據源
阿新 • • 發佈:2018-02-03
catch move pos object trac ble 適配器 動態 user
1、裝飾設計模式
package com.itheima.ds; 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; //目前要包裝的是:com.mysql.jdbc.Connection //1、編寫一個類,實現與被包裝類(數據庫驅動對Connection的實現)相同的接口。(使這個類和數據庫的驅動實現有著相同的行為)public class MyConnection implements Connection { // 2、定義一個變量,引用被包裝類的實例 private Connection conn;//引用具體的數據庫驅動 private List<Connection> pool; // 3、定義構造方法,傳入被包裝類的實例。 public MyConnection(Connection conn,List<Connection> pool){//依賴註入 this.conn = conn;this.pool = pool; } //把鏈接還回池中 // 4、對於要改寫的方法,編寫自己的代碼即可。 public void close() throws SQLException { pool.add(conn); } public Statement createStatement() throws SQLException { return conn.createStatement(); } //5、對於不需要改寫的方法,調用原有對象的對應方法。 public <T> T unwrap(Class<T> iface) throws SQLException { return conn.unwrap(iface); } }
package com.itheima.ds; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.sql.DataSource; import com.itheima.util.JdbcUtil; public class MyDataSource1 implements DataSource { private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>()); static{ try { for(int i=0;i<10;i++){ Connection conn = JdbcUtil.getConnection();//創建的新連接 pool.add(conn); } } catch (Exception e) { e.printStackTrace(); } } //從池中獲取鏈接 > com.mysql.jdbc.Connection public Connection getConnection() throws SQLException { if(pool.size()>0){ Connection conn = pool.remove(0); MyConnection1 mconn = new MyConnection1(conn,pool); return mconn; }else{ throw new RuntimeException("服務器真忙"); } } public PrintWriter getLogWriter() throws SQLException { return null; } public void setLogWriter(PrintWriter out) throws SQLException { } public void setLoginTimeout(int seconds) throws SQLException { } public int getLoginTimeout() throws SQLException { return 0; } public <T> T unwrap(Class<T> iface) throws SQLException { return null; } public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; } public Connection getConnection(String username, String password) throws SQLException { return null; } }
2、適配器設計模式
package com.itheima.ds; 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.Map; import java.util.Properties; //默認的適配器 /* 本身也是一個包裝類,但並沒有對任何的方法進行改寫 1、編寫一個類,實現與被包裝類(數據庫驅動對Connection的實現)相同的接口。(使這個類和數據庫的驅動實現有著相同的行為) 2、定義一個變量,引用被包裝類的實例。 3、定義構造方法,傳入被包裝類的實例。 4、全部調用原有對象的對應方法 */ public class ConnectionAdapter implements Connection { private Connection conn; public ConnectionAdapter(Connection conn){ this.conn = conn; } public <T> T unwrap(Class<T> iface) throws SQLException { return conn.unwrap(iface); } public boolean isWrapperFor(Class<?> iface) throws SQLException { return conn.isWrapperFor(iface); } @Override public Statement createStatement() throws SQLException { return conn.createStatement(); } ...... }
package com.itheima.ds; import java.sql.Connection; import java.sql.SQLException; import java.util.List; /* 這也是包裝:對ConnectionAdapter進行包裝。 包裝類即是被包裝類的包裝,又是他的子類。 1、編寫一個類,繼承已經是包裝類的類。 2、定義一個變量,引用被包裝類的實例。 3、定義構造方法,傳入被包裝類的實例。 4、覆蓋掉需要改寫的方法 */ public class MyConnection1 extends ConnectionAdapter { private Connection conn; private List<Connection> pool; public MyConnection1(Connection conn,List<Connection> pool){ super(conn); this.conn = conn; this.pool = pool; } public void close() throws SQLException { pool.add(conn); } }
3、基於接口的動態代理:Proxy
package com.itheima.ds; 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.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.sql.DataSource; import com.itheima.util.JdbcUtil; //用動態代理編寫的數據源 public class MyDataSource2 implements DataSource { private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>()); static{ try { for(int i=0;i<10;i++){ Connection conn = JdbcUtil.getConnection();//創建的新連接 pool.add(conn); } } catch (Exception e) { e.printStackTrace(); } } public Connection getConnection() throws SQLException { if(pool.size()>0){ final Connection conn = pool.remove(0);//得到的是數據庫驅動的實現 Connection connProxy = (Connection)Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if("close".equals(method.getName())){ //還回池中 return pool.add(conn); }else{ return method.invoke(conn, args); } } } ); return connProxy;//返回30行的代理對象 }else{ throw new RuntimeException("服務器真忙"); } }
package com.itheima.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class Client1 { public static void main(String[] args) { final Human sb = new SpringBrother(); //代理人:如何動態產生代理人 /* ClassLoader loader:動態代理,必須有字節碼class。加到內存中運行,必須有類加載器。固定:和被代理人用的是一樣的 Class<?>[] interfaces:代理類要實現的接口,要和被代理對象有著相同的行為。固定:和被代理人用的是一樣的 InvocationHandler h:如何代理。他是一個接口。策略設計模式。 */ //產生代理類,得到他的實例 Human proxyMan = (Human)Proxy.newProxyInstance(sb.getClass().getClassLoader(), sb.getClass().getInterfaces(), new InvocationHandler() { //匿名內部類,完成具體的代理策略 //調用代理類的任何方法,都會經過該方法。 攔截 /* Object proxy:對代理對象的引用。 Method method:當前執行的方法 Object[] args:當前方法用到的參數 返回值:當前調用的方法的返回值 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //判斷出場費 if("sing".equals(method.getName())){ //唱歌 float money = (Float)args[0]; if(money>10000){ method.invoke(sb, money/2); } } if("dance".equals(method.getName())){ //唱歌 float money = (Float)args[0]; if(money>20000){ method.invoke(sb, money/2); } } return null; } } ); proxyMan.sing(20000); proxyMan.dance(100000); } }
4、基於子類的動態代理:CGLIB
前提:被代理類的要求
1、不能是final的
2、必須是public的
package com.itheima.cglib; import java.lang.reflect.Method; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class Client1 { public static void main(String[] args) { final SpringBrother sb = new SpringBrother(); //產生sb的代理: /* Class type:代理類的父類型 Callback cb:回調,如何代理 */ SpringBrother proxy = (SpringBrother) Enhancer.create(SpringBrother.class,new MethodInterceptor(){ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy arg3) throws Throwable { //判斷出場費 if("sing".equals(method.getName())){ //唱歌 float money = (Float)args[0]; if(money>10000){ method.invoke(sb, money/2); } } if("dance".equals(method.getName())){ //唱歌 float money = (Float)args[0]; if(money>20000){ method.invoke(sb, money/2); } } return null; } }); System.out.println(proxy instanceof SpringBrother); proxy.dance(100000); proxy.sing(50000); } }
Java編寫準備數據源