程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA編程入門知識 >> JDK動態代理堆棧圖詳解--干貨

JDK動態代理堆棧圖詳解--干貨

編輯:JAVA編程入門知識
首先我們有一個數據源模型命名為User,其中包括username 和 password這兩個屬性 和他們的set get方法
public class User {
    private String username;
    private String password;
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

  

接著一個UserDAO接口
public interface UserDAO {
    public void save(User user);
    public void delete();
}

  

在一個實現該接口的類
public class UserDAOImpl implements UserDAO {
 
    public void save(User user) {
 
        System.out.println("user saved!");
    }
 
    public void delete() {
        System.out.println("user deteleted");
 
    }
 
}

  

接著就是動態代理了 實現invocationHandler的類
public class LogInterceptor implements InvocationHandler {
    private Object target;
 
    public Object getTarget() {
        return target;
    }
 
    public void setTarget(Object target) {
        this.target = target;
    }
 
    public void beforeMethod(Method m) {
 
        System.out.println(m.getName() + " start");
    }
 
    public Object invoke(Object proxy, Method m, Object[] args)
            throws Throwable {
        beforeMethod(m);
        m.invoke(target, args);
        return null;
    }
}

  

最後我們采取單元測試了 寫一個單元測試
@Test
    public void testProxy() {
        UserDAO userDAO = new UserDAOImpl();
        LogInterceptor li = new LogInterceptor();
        li.setTarget(userDAO);
        UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
        System.out.println(userDAOProxy.getClass());
        System.out.println(userDAOProxy.getClass().getInterfaces());
        userDAOProxy.delete();
        userDAOProxy.save(new User());
 
    }

  

當調用這句話的時候 UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li); 我們創建了一個代理對象userDAOProxy 當執行該句的時候 userDAOProxy.delete();  userDAOProxy對象是由Proxy的靜態方法newProxyInstance產生的,該方法後面跟著三個參數分別為 userDAO的類加載器,類的所有接口,和一個實現了invocationHandler 的類LogInterceptor 執行步驟如下  1 執行LogInterceptor對象的invoke方法 2 invoke方法的第一條語句為beforeMethod(m);故跳轉至beforeMethod(m);函數 3執行beforeMethod(m)函數的System.out.println(m.getName() + " start")語句 console中打印出了delete start 在這裡為什麼是delete呢,因為我們上面執行的是userDAOProxy.delete()方法,故m.getName()中的m就是delete方法 beforeMethod(m);執行完畢 4 執行m.invoke(target, args); 如上圖所示直接跳到了UserDAOImpl實例的delete方法 打印台輸出該方法的輸出user deteleted 重新回到invoke方法的 m.invoke(target, args);語句 一個動態代理的過程就結束了。 從這個過程宗我們可以看到 當我們使用動態代理對象的方法時候,首先回去調用invoke方法,該方法有參數Method m,也就是我們使用的方法。 我們在該invoke方法中會加入橫向切面邏輯如上面的例子beforeMethod(Method m)方法,該邏輯執行完後通過調用m.invoke(target, args)去執行被代理對象中我們原有的方法。一個代理過程就完成了 下面是我針對這整個項目畫的一個圖 應該更加方便理解
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved