1. 程式人生 > 實用技巧 >靜態代理與動態代理模式

靜態代理與動態代理模式

1.靜態代理模式

  • 靜態代理角色分析

    抽象角色:一般由介面或抽象類來實現

    真實角色:實現抽象角色的實現類,也是被代理的角色

    代理角色:代理真是角色,一般會做一些附屬操作,比如記錄日誌等

    客戶:使用代理角色進行一下操作

  • 抽象角色

    public interface UserService {
    
        void add();
    
        void update();
    
        void query();
    
        void delete();
    
    }
    
  • 真實角色

    public class UserServiceImpl implements UserService{
    
        @Override
        public void add() {
            System.out.println("添加了一個使用者!");
        }
        @Override
        public void update() {
            System.out.println("修改了一個使用者!");
        }
        @Override
        public void query() {
            System.out.println("查詢了一個使用者!");
        }
        @Override
        public void delete() {
            System.out.println("刪除了一個使用者!");
        }
    }
    
  • 代理角色

    public class UserServicePoxy implements UserService {
    
        private UserService userService;
    
        public void setUserService(UserService userService) {
            this.userService = userService;
        }
        @Override
        public void add() {
            userService.add();
            addLog("新增");
        }
        @Override
        public void update() {
            userService.update();
            addLog("修改");
        }
        @Override
        public void query() {
            userService.query();
            addLog("查詢");
        }
        @Override
        public void delete() {
            userService.delete();
            addLog("刪除");
        }
        public void addLog(String methodName){
            System.out.println("【日誌】"+methodName+"一個使用者!");
        }
    }
    
  • 客戶

    public class MyTest {
    
        public static void main(String[] args) {
            //建立真實物件
            UserService userService = new UserServiceImpl();
            //建立代理
            UserServicePoxy userServicePoxy = new UserServicePoxy();
            //將真實物件交給代理
            userServicePoxy.setUserService(userService);
            //用代理去新增使用者
            userServicePoxy.add();
        }
    
    }
    

2.動態代理模式

​ 動態代理的角色與靜態代理一樣,只不過動態代理的代理類是動態生成的。動態代理分為基於介面的動態代理和基於類的動態代理。

- 基於介面的動態代理—JDK動態代理;

- 基於類的動態代理—cglib;

- 現在用的比較多的是用javasist來生成動態代理。

​ JDK動態代理需要了解兩個類InvocationHandler和Proxy。

InvocationHander[程式處理]

​ 其invoke方法是代理角色在呼叫真實角色的處理方法時,會呼叫該方法,並用反射的方式實現真實角色的方法。

Proxy 代理

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

生成代理角色,loader 類載入器,interfaces 抽象角色的class物件集合,h 處理程式的實體類

  • 抽象角色
public interface UserService {
    void add();
    void update();
    void query();
    void delete();
}
  • 真實角色

    public class UserServiceImpl implements UserService {
        @Override
        public void add() {
            System.out.println("添加了一個使用者!");
        }
        @Override
        public void update() {
            System.out.println("修改了一個使用者!");
        }
    
        @Override
        public void query() {
            System.out.println("查詢了一個使用者!");
        }
        @Override
        public void delete() {
            System.out.println("刪除了一個使用者!");
        }
    }
    
  • 動態代理處理程式

    /**
     * 代理例項的呼叫處理程式介面實現類
     */
    public class ProxyInvocationHandler implements InvocationHandler {
        private Object target;
        public void setTarget(Object target) {
            this.target = target;
        }
        //代理角色呼叫真實角色中的方法時會呼叫invoke方法來實現真實角色中的方法(反射的思想)
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            log(method.getName());
            Object result = method.invoke(target,args);
            return result;
        }
    
        //生成代理類
        public Object getProxy(){
            return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        }
        void log(String msg){
            System.out.println("執行了"+msg+"方法!");
        }
    }
    
  • 客戶端

    public static void main(String[] args) {
        //建立真實角色
        UserService userService = new UserServiceImpl();
        //建立處理程式
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //將真實角色注入到處理程式中,為代理做準備
        pih.setTarget(userService);
        //生成代理類
        UserService proxy = (UserService) pih.getProxy();
        //執行新增方法 其實是通過處理程式中的invoke呼叫真實角色中的add方法
        proxy.add();
    }
    
  • 執行結果