java方法增強(qiáng)的三種方式:繼承,裝飾和代理

在java中,在不改變源代碼的情況下,實(shí)現(xiàn)方法增強(qiáng)的方式有三種:

  • 1,繼承
  • 2,裝飾者模式
  • 3,代理模式(靜態(tài)代理和動態(tài)代理)
1,繼承模式:
  • 簡單來說,就是通過繼承的方式,在子類方法中添加相應(yīng)的增強(qiáng)方法,然后通過調(diào)用子類方法來實(shí)現(xiàn)增強(qiáng)。
//繼承比較簡單,直接繼承,重寫中調(diào)用父類方法即可
2,裝飾者模式:
  • 裝飾者模式是真正完全不改變源碼的情況下增強(qiáng)方法的一種方式,即便是調(diào)用方式也無需改變
  • 這里用自定義的連接池來進(jìn)行說明
  • 在自定義連接池中,如果沒有增強(qiáng)過Connection的話,那么是不能按照原來的方式直接調(diào)用connection.close();方法的,那么可以通過裝飾,把連接池中的Connection對象直接在放入池之前包裝成我自定義的Connection,這樣從連接池中取出來的連接也是我自定義的連接,那么只需要在自定義的方法中實(shí)現(xiàn)close()和prepareStatement等就可以達(dá)到直接調(diào)用關(guān)閉方法的目的,具體如下:
//1,自定義連接池
/*
 * 對JDBC連接的封裝,也就是自定義連接池
 * 其他一些方法也需要重寫,但是不需要任何改變,所以這里就沒有貼出來
 */
public class JDBCDatasource implements DataSource {
    private static LinkedList<Connection> connections = new LinkedList<Connection>();
    //往連接池中添加連接
    static{
        for(int i=0;i<5;i++){
            Connection connection = JDBCUtil.getConnection();
            JDBCConnection theConnection = new JDBCConnection(connections, connection);
            connections.add(theConnection);
        }
    }
    //重寫這一個方法,如果沒有增強(qiáng)過connection的話,需要調(diào)用這個方法歸還連接到連接池中
    @Override
    public Connection getConnection() throws SQLException {
        if (connections.size() == 0) {
            for(int i=0;i<5;i++){
                Connection connection = JDBCUtil.getConnection();
                JDBCConnection theConnection = new JDBCConnection(connections, connection);
                connections.add(theConnection);
            }
        }
        return connections.removeFirst();
    }
     //新增一個方法
    public void returnConnection(Connection connection){
        connections.add(connection);
    }
}

//2,自定義連接類,實(shí)現(xiàn)相應(yīng)的方法,并在自定義的連接池中進(jìn)行包裝,具體看1中的代碼
//其他一些不需要修改的覆蓋方法這里不再貼出
public class JDBCConnection implements Connection {
    private Connection connection;
    private LinkedList<Connection> connections;
    public JDBCConnection(List<Connection> connections, Connection connection) {
        this.connections = (LinkedList<Connection>) connections;
        this.connection = connection;
    }
    //如果想要在關(guān)閉的時候添加到連接池,那么需要把連接池傳進(jìn)來,傳進(jìn)來最好的時候就是創(chuàng)建的時候
    @Override
    public void close() throws SQLException {
        System.out.println("here here!");
        connections.add(connection);
    }
    @Override
    public PreparedStatement prepareStatement(String sql) throws SQLException {
        return connection.prepareStatement(sql);
    }
}

//測試
JDBCDatasource datasource = new JDBCDatasource();
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
    connection = datasource.getConnection();
    preparedStatement = connection.prepareStatement("select * from product;");
    resultSet = preparedStatement.executeQuery();
    while(resultSet.next()){
        System.out.println(resultSet.getString("pname"));
    }
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    //這行代碼中封裝了connection.close()方法
    JDBCUtil.closeAll(connection, preparedStatement, resultSet);
}

3,代理模式:
  • 代理分為動態(tài)代理和靜態(tài)代理,區(qū)別就是靜態(tài)代理是自己創(chuàng)建一個代理類,實(shí)現(xiàn)相應(yīng)的被代理對象的方法,增加相應(yīng)的增強(qiáng)代碼。而動態(tài)代理是通過類加載器,反射等在運(yùn)行時創(chuàng)建代理類,也就是不需要手動創(chuàng)建代理類,在對應(yīng)的代理方法newProxyInstance中的代碼塊中直接添加增強(qiáng)代碼;
  • 動態(tài)代理是在靜態(tài)代理的基礎(chǔ)上的拓展,所以先看下靜態(tài)代理:
//1,首先需要有一個接口類,方便目標(biāo)對象和代理對象去實(shí)現(xiàn)
public interface DogInterface {
    public void eat();
    public void run();
}

//2,目標(biāo)對象中實(shí)現(xiàn)借口類
public class Dog implements DogInterface {
    @Override
    public void eat() {
        System.out.println("Dog  -----eat");
    }
    @Override
    public void run() {
        System.out.println("dog----run----");
    }
}

//3,創(chuàng)建一個代理對象,在代理對象中實(shí)現(xiàn)借口類,并在對應(yīng)的方法中調(diào)用目標(biāo)對象的方法。
public class DogProxy implements DogInterface {
    @Override
    public void eat() {
        System.out.println("dog在eat前,準(zhǔn)備工作代碼等");
                //這里調(diào)用目標(biāo)對象的方法
        Dog dog = new Dog();
        dog.eat();
        System.out.println("dog在eat后收尾工作代碼等");
    }
    @Override
    public void run() {
    }
}

//4,實(shí)際使用時候使用代理對象即可
public void proxyTest(){
    DogProxy proxy = new DogProxy();
    proxy.eat();//這里就ok了
}
  • 下面是動態(tài)代理的代碼實(shí)現(xiàn),前兩步是完全一致的
    有一點(diǎn)需要注意的是:動態(tài)代理方法雖然能增強(qiáng)方法,但主要的使用場合是在攔截中進(jìn)行相應(yīng)的處理,如在全局的攔截器中進(jìn)行亂碼處理等
//1,首先需要有一個接口類,方便目標(biāo)對象和代理對象去實(shí)現(xiàn)
public interface DogInterface {
    public void eat();
    public void run();
}

//2,目標(biāo)對象中實(shí)現(xiàn)借口類
public class Dog implements DogInterface {
    @Override
    public void eat() {
        System.out.println("Dog  -----eat");
    }
    @Override
    public void run() {
        System.out.println("dog----run----");
    }
}

//3,在調(diào)用的時候使用代理類調(diào)用靜態(tài)方法創(chuàng)建動態(tài)代理
 public void dynamicProxyTest(){
    DogInterface proxy = (DogInterface) Proxy.newProxyInstance(
            Dog.class.getClassLoader(), 
            Dog.class.getInterfaces(), //new Class[]{DogInterface.class}
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("before");
                    method.invoke(new Dog(), args);
                    System.out.println("after");
                return null;
        }
    });
    proxy.eat();
    proxy.run();
}
//搞定!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,897評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,715評論 19 139
  • 轉(zhuǎn)自:http://blog.csdn.net/jackfrued/article/details/4492194...
    王帥199207閱讀 8,813評論 3 93
  • 文章作者:Tyan博客:noahsnail.com Chapter 2 Creating and Destroyi...
    SnailTyan閱讀 727評論 0 1
  • 不如意事常八九,可與語人無二三。 淡漠的性格,不是生下來就有的,更多的是因?yàn)槿饲榈∷?。每次總是付出百分?..
    蟬茶閱讀 404評論 0 1

友情鏈接更多精彩內(nèi)容