天天看點

面試問到AOP就該這樣回答

前言

  相信各位小夥伴在準備面試的時候,AOP都是無法繞過的一個點,經常能看到動态代理、JDK動态代理、CGLIB動态代理這樣的字眼。其實動态代理是代理模式的一種。代理模式有靜态代理、強制代理、動态代理。是以在認識AOP之前需要了解代理模式。

代理模式定義

  代理模式(Proxy Pattern):為其他對象提供一種代理以控制這個對象的通路。

  • Subject抽象主題角色,也叫做抽象主題類。可以是抽象類也可以是接口,是一個最普通的業務類型定義,無特殊要求。
  • RealSubject具體主題角色,也叫做被委托角色,被代理角色,是業務邏輯的具體執行者。
  • Proxy代理主題角色,也叫做委托類、代理類。他負責對真實角色的應用,把所有抽象主題類定義的方法限制委托給真實主題角色實作,并且在真實主題角色處理完畢前後做到預處理和善後工作。

代理模式的優點

  • 職責清晰
  • 高擴充性
  • 智能化

UML

面試問到AOP就該這樣回答

我的了解

  跳闆機不管是對于運維老哥還是對于我們來講,都是日常的工作中不可或缺的一個工具。為了保證生産伺服器的安全,我們是無法通過xshell等工具直接進行連接配接的。如果需要操作生産的伺服器,則需要通過跳闆機。并且跳闆機還能記錄我們的操作,用來做安全審計。防止出現,某位老哥一氣之下反手就是個

sudo rm -rf /*

直接涼涼。

面試問到AOP就該這樣回答

  我們回過頭看看代理模式的定義:為其他對象提供一種代理以控制這個對象的通路。實際上跳闆機就是生産伺服器的一個代理

Proxy

,為了實作控制生産伺服器的通路權限。你需要通過跳闆機來操作生産伺服器。

  • 為其他對象提供一種代理以控制這個對象的通路
  • 給你提供一個跳闆機來通路生産伺服器,目的是來控制生産伺服器的通路

  

Proxy

的職責:

Proxy

是對真實角色的應用,把所有抽象主題類定義的方法限制委托給真實主題角色實作。并且在真實主題角色處理完畢前後做到預處理和善後工作。你通過操作跳闆機。跳闆機将你輸入的指令在生産伺服器上進行執行。并且能記錄下執行的指令和執行的結果。

代碼示範

Server

public interface Server {

    /**
     * 執行
     * @param command 指令
     */
    void exec(String command);

}           

ProdServer

public class ProdServer implements Server {

    @Override
    public void exec(String command){
        System.out.println(command + ":執行成功");
    }

}           

JumpServer

public class JumpServer {

    private Server server;

    public JumpServer(Server server) {
        this.server = server;
    }

    public void exec(String command){
        System.out.println("xxx在:" + LocalDateTime.now() + " 執行了:" + command);
        server.exec(command);
        System.out.println("xxx在:" + LocalDateTime.now() + " 執行完了:"+ command + " 結果是XXX");
    }

}           

Client

public class Client {

    public static void main(String[] args) {
        JumpServer jumpServer = new JumpServer();
        jumpServer.exec("pwd");
    }
}           

運作結果

xxx在:2020-04-04T16:43:19.277 執行了:pwd
pwd:執行成功
xxx在:2020-04-04T16:43:19.278 執行完了:pwd 結果是XXX           

  通過上面的代碼,簡單的實作了代理模式。在網絡上代理伺服器設定分為透明代理和普通代理。

  • 透明代理就是使用者不用設定代理伺服器位址,就可以直接通路.也就是說代理伺服器對使用者來說是透明的,不用知道它存在的。
  • 普通代理則是需要使用者自己設定代理伺服器的IP位址,使用者必須知道代理的存在。

  當運維老哥給了一台伺服器的賬号和密碼,你成功登入,并完成了相應的操作。你以為給你的是生産的伺服器。實際就可能是個跳闆機。為了安全起見,是不可能将實際伺服器的IP讓你知道的。很顯然跳闆機對你來講就是透明的。

面試問到AOP就該這樣回答

是以我們調整一下代碼,将其變成普通代理

public class JumpServer {

    private Server server;

    public JumpServer(Server server) {
        this.server = server;
    }

    public void exec(String command){
        server.exec(command);
    }

}           
public class Client {

    public static void main(String[] args) {
        ProdServer prodServer = new ProdServer();
        JumpServer jumpServer = new JumpServer(prodServer);
        jumpServer.exec("pwd");
    }
    
}           

執行結果

xxx在:2020-04-04T16:52:23.282 執行了:pwd
pwd:執行成功
xxx在:2020-04-04T16:52:23.283 執行完了:pwd 結果是XXX           

強制代理

  對于現實情況,我們可以通過不開放公網通路的權限來實作,強制使用代理操作伺服器。我們可以用代碼簡單的模拟下。

public class ProdServer implements Server {

    private JumpServer jumpServer;

    @Override
    public void exec(String command){
        hasProxy();
        System.out.println(command + ":執行成功");
    }

    private void hasProxy(){
        if(jumpServer == null){
            throw new RuntimeException("請使用跳闆機!");
        }
    }

    public JumpServer setJumpServer() {
        this.jumpServer = new JumpServer(this);
        return this.jumpServer;
    }
}           

Client未設定跳闆機

public class Client {

    public static void main(String[] args) {
        ProdServer prodServer = new ProdServer();
        prodServer.exec("pwd");
    }

}           

這個時候需要通路生産伺服器,就需要先設定跳闆機了,才能進行操作。

動态代理

  對靜态代理來說,我們需要手動生成代理類。但是如果需要代理的類太多了,那這個肯定是不可取的。是以我們可以使用JDK動态代理來幫我們完成工作。

面試問到AOP就該這樣回答