Java編程思想之代理

一:靜態代理

這種代理方式需要代理對象和目標對象實現一樣的接口

優點:可以在不修改目標對象的情況下擴展目標對象的功能(經紀人是明星的代理,可以爲明星做另外的一些事情)

缺點:

  1. 冗餘。由於代理對象要實現與目標對象一致的接口,會產生過多的代理類。
  2. 不易維護。一旦接口增加方法,目標對象與代理對象都要進行修改。

 

舉例:

//接口IUserDao

package com.proxy;

 

public interface IUserDao {

    public void save();

}

 

//目標對象UserDao

package com.proxy;

 

public class UserDao implements IUserDao{

 

    @Override

    public void save() {

        System.out.println("保存數據");

    }

}

 

//靜態代理對象:UserDapProxy 需要實現IUserDao接口!

package com.proxy;

 

public class UserDaoProxy implements IUserDao{

 

    private IUserDao target;

    public UserDaoProxy(IUserDao target) {

        this.target = target;

    }

   

    @Override

    public void save() {

        System.out.println("開啓事務");//擴展了額外功能

        target.save();

        System.out.println("提交事務");

    }

}

 

//測試類:TestProxy

package com.proxy;

 

import org.junit.Test;

 

public class StaticUserProxy {

    @Test

    public void testStaticProxy(){

        //目標對象

        IUserDao target = new UserDao();

        //代理對象

        UserDaoProxy proxy = new UserDaoProxy(target);

        proxy.save();

    }

}

 

輸出結果:

開啓事務

保存數據

提交事務

 

二:動態代理

1:動態代理利用了JDK API,動態地在內存中構建代理對象,從而實現對目標對象的代理功能。動態代理又被稱爲JDK代理或接口代理。

2:動態代理對象不需要實現接口,但是要求目標對象必須實現接口,否則不能使用動態代理。

3:動態代理利用了反射的機制,我們在運行時動態的利用反射獲取目標對象的方法,這個代理代碼較爲通用,不是爲某個具體的目標對象而創建,是一種抽象。

目標接口和目標對象實現相同

//動態代理對象

package com.proxy;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

 

public class ProxyFactory {

 

    private Object target;// 維護一個目標對象

public ProxyFactory(Object target) {

        this.target = target;

    }

 

    // 爲目標對象生成代理對象

    public Object getProxyInstance() {

        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),

                new InvocationHandler() {

                 @Override

                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        System.out.println("開啓事務");

 

                        // 執行目標對象方法

                        Object returnValue = method.invoke(target, args);

                         System.out.println("提交事務");

                        return null;

                    }

                });

    }

}

 

測試類:

package com.proxy;

 

import org.junit.Test;

 

public class TestProxy {

 

    @Test

    public void testDynamicProxy (){

        IUserDao target = new UserDao();

        System.out.println(target.getClass());  //輸出目標對象信息

        IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();

        System.out.println(proxy.getClass());  //輸出代理對象信息

        proxy.save();  //執行代理方法

    }

}

輸出結果:

開啓事務

保存數據

提交事務

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章