首頁 > Java > java教程 > 主體

java之動態代理

高洛峰
發布: 2016-12-01 13:30:52
原創
1281 人瀏覽過

一、動態代理引入

package cn2;
 
public interface IUserDAO {
    /**
     * 登录方法
     */
    public void login();
     
    /**
     * 注册方法
     */
    public void register();
 
}
package cn2;
 
public class UserDAOImpl implements IUserDAO {
 
    @Override
    public void login() {
        System.out.println("用户登录");
 
    }
 
    @Override
    public void register() {
        System.out.println("用户注册");
    }
 
}
package cn2;
 
public class Test {
    public static void main(String[] args) {
        IUserDAO dao = new UserDAOImpl();
        dao.register();
        dao.login();
         
         
    }
}
登入後複製

用戶註冊

用戶登入


如果我要給每個方法增加權限校驗和日誌記錄權限的話,那麼程式碼實作如下:

package cn2;
 
public interface IUserDAO {
    /**
     * 登录方法
     */
    public void login();
     
    /**
     * 注册方法
     */
    public void register();
 
}
package cn2;
 
public class UserDAOImpl implements IUserDAO {
 
    @Override
    public void login() {
        System.out.println("用户登录");
 
    }
 
    @Override
    public void register() {
        System.out.println("用户注册");
    }
 
}
package cn2;
 
public class UserDAOImpl2 implements IUserDAO {
    private void actionCheck(){
        System.out.println("权限检查");
    }
     
    private void record(){
        System.out.println("日志记录");
    }
     
    @Override
    public void login() {
        this.actionCheck();
        System.out.println("登录");
        this.record();
 
    }
 
    @Override
    public void register() {
        this.actionCheck();
        System.out.println("注册");
        this.record();
    }
 
}
package cn2;
 
public class Test {
    public static void main(String[] args) {
        IUserDAO dao = new UserDAOImpl2();
        dao.register();
        dao.login();
         
         
    }
}
登入後複製

reee

日誌記錄

權限檢查

登入

日誌記錄


為什麼要單獨寫一個類別去實現接口,並增加校驗和日誌記錄呢?因為我們在設計的時候,要確保對擴充功能開發,對修改程式碼關閉的原則。我定義了一個新的類別去實作接口,就是想擴展原來接口的功能,而不是在原有的實作類別上修改。

但是,如果都這樣設計,是很可怕的事情,如果需求一旦變更,那我們需要定義好多好多的實現類,太複雜了。怎麼辦?


在生活中,我們會遇到很多問題,例如:我要租房子,但是我不認識房東,怎麼辦?找仲介。同樣的道理,我自己不想在修改程式碼去增加權限檢查和日誌記錄的功能,那麼我找一個代理物件去幫我實作不就可以了嗎?


動態代理:就是在程式運作過程中產生的這個物件。


在Java中java.lang.reflect套件下提供了一個Proxy類別和一個InvocationHandler接口,透過使用這個類別和介面接可以產生動態代理物件。 JDK只針對介面做代理。


Proxy類別中的方法建立動態代理物件

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
登入後複製

   

最終會呼叫InvocationHandler的方法

Object invoke(Object proxy,Method method,Object[] args)
登入後複製
package cn2;
 
public interface IUserDAO {
    /**
     * 登录方法
     */
    public void login();
     
    /**
     * 注册方法
     */
    public void register();
 
}
package cn2;
 
public class UserDAOImpl implements IUserDAO {
 
    @Override
    public void login() {
        System.out.println("用户登录");
 
    }
 
    @Override
    public void register() {
        System.out.println("用户注册");
    }
 
}
package cn2;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
public class MyInvocationHandler implements InvocationHandler {
     
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
     
    /**
     *返回动态代理对象
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
         
        System.out.println("权限检查");
         
        Object invoke = method.invoke(target, args);
         
        System.out.println("日志记录");
        return invoke;
    }
 
}
package cn2;
 
import java.lang.reflect.Proxy;
 
public class Test {
    public static void main(String[] args) {
        //使用动态代理之前
        IUserDAO dao = new UserDAOImpl();
        dao.register();
        dao.login();
         
        System.out.println("-------------------");
         
        //使用动态代理之后
         
        IUserDAO proxy = (IUserDAO)Proxy.newProxyInstance(dao.getClass().getClassLoader(), dao.getClass().getInterfaces(), new MyInvocationHandler(dao));
        proxy.register();
        proxy.login();
         
    }
}
登入後複製
 ---------

權限檢查

用戶註冊

日誌記錄

權限檢查

用戶登入

日誌記錄

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!