1. 程式人生 > 其它 >Maven環境配置常見問題

Maven環境配置常見問題

代理模式的簡易實現

代理模式

代理模式通俗的將就是原來是自己做的事,現在交給別人去做

代理模式可以在不修改被代理物件的基礎上,通過擴充套件代理類,進行一些功能的附加與增強

  • 代理類和被代理類需要繼承同一個介面,有相同的行為
  • 介面中的方法就可以被代理執行
  • 使用者在通過介面呼叫方法時,執行的是代理類中實現的方法
  • 在代理類的內部,呼叫了被代理類
  • 實際介面的實現是由被代理類實現的
  • 代理類可以在原來的基礎上擴充套件

代理又有靜態代理和動態代理

靜態代理

通過例子來模擬靜態代理

模擬一下,委託別人買票的例子

我有1000元,想買一張票,但是自己買不到,委託別人去給我買,但是他需要收取小費才給我買票

首先要有一個共同的買票的行為,就是共同的介面

public interface BuyTicket {

    void buy(float money);
}

被代理人真正的實現這個介面

public class BuyTicketImpl implements BuyTicket {
    @Override
    public void buy(float money) {
        System.out.println("購票成功,花費了" + money + "元!");
    }
}

代理類通過構造器的方式將被代理類傳遞進來,並在買票之前收取小費

public class ProxyBuyTicketImpl implements BuyTicket {

    private BuyTicketImpl buyTicket;

    public ProxyBuyTicketImpl(BuyTicketImpl buyTicket) {
        this.buyTicket = buyTicket;
    }

    @Override
    public void buy(float money) {
        // 在買票之前需要收100小費
        money -= 100;
        System.out.println("收取了100的小費!");
        // 再真正的執行買票的操作
        buyTicket.buy(money);
    }
}
@Test
public void test1(){
	// 被代理類
	BuyTicketImpl buyTicket = new BuyTicketImpl();
	// 代理類
	ProxyBuyTicketImpl proxyBuyTicket = new ProxyBuyTicketImpl(buyTicket);
	proxyBuyTicket.buy(1000);
}

代理類和被代理類應該共同實現一個介面,或者是共同繼承某個類
靜態代理的型別是事先就確定好的,所以叫做動態代理

基於JDK的動態代理

JDK中提供了一個Proxy類來實現動態代理

該類中提供了一個newProxyInstance

返回指定介面的代理類的例項

public static Object newProxyInstance(
    ClassLoader loader,
    Class<?>[] interfaces,
    InvocationHandler h
) throws IllegalArgumentException
  • loader 類載入器來定義代理類
  • interfaces 代理類實現的介面列表
  • h 排程方法呼叫的呼叫處理函式,這個就是代理具體要做的事情

依然是剛才的例子,使用JDK的動態代理來實現

首先要寫一個排程方法

public class MyInvocationHandler implements InvocationHandler {

    BuyTicketImpl buyTicket;

    public MyInvocationHandler(BuyTicketImpl buyTicket) {
        this.buyTicket = buyTicket;
    }

    /**
    * 代理執行的具體操作
    */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if ("buy".equals(method.getName())){
            float money = (float) args[0];
            money -= 100;
            System.out.println("收了100的小費!");
            method.invoke(buyTicket, money);
        }
        return null;
    }
}

建立代理物件

@Test
public void test2(){
	// 被代理物件
	BuyTicketImpl buyTicket = new BuyTicketImpl();
	// 建立代理物件
	BuyTicket proxy = (BuyTicket) Proxy.newProxyInstance(
		buyTicket.getClass().getClassLoader(),
		buyTicket.getClass().getInterfaces(),
		new MyInvocationHandler(buyTicket)
	);
	// 代理執行
	proxy.buy(1000);
}

使用JDK的動態代理,我們就可以動態的生成代理,可以很方便的生成多個不同的代理

JDK的動態代理需要有一個代理的介面

基於cglib的動態代理

使用cglib的動態代理需要使用兩個包
asm-4.1.jar
cglib-3.1.jar

並且使用cglib動態代理不需要介面就可以實現,可以直接給類建立一個代理物件

比如還是買票的例子

現在我只有類 並沒有實現介面

public class BuyTicketImpl{
    public void buy(float money) {
        System.out.println("購票成功,花費了" + money + "元!");
    }
}

使用cglib動態代理

@Test
public void test03(){
	// 被代理物件
	BuyTicketImpl buyTicket = new BuyTicketImpl();

	//建立代理
	BuyTicketImpl buyTicketProxy = (BuyTicketImpl)Enhancer.create(buyTicket.getClass(), new InvocationHandler() {
		@Override
		public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
			if ("buy".equals(method.getName())) {
				float money = (float) objects[0];
				money -= 100;
				System.out.println("收了100的小費!");
				method.invoke(buyTicket, money);
			}
			return null;
		}
	});
	buyTicketProxy.buy(1000);
}

使用cglib也需要一個InvocationHandler出來,裡面的方法就是具體代理要做的內容