1. 程式人生 > >Java編寫準備數據源

Java編寫準備數據源

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編寫準備數據源