Maven環境配置常見問題
阿新 • • 發佈:2021-11-21
代理模式的簡易實現
返回指定介面的代理類的例項
代理模式
代理模式通俗的將就是原來是自己做的事,現在交給別人去做
代理模式可以在不修改被代理物件的基礎上,通過擴充套件代理類,進行一些功能的附加與增強
- 代理類和被代理類需要繼承同一個介面,有相同的行為
- 介面中的方法就可以被代理執行
- 使用者在通過介面呼叫方法時,執行的是代理類中實現的方法
- 在代理類的內部,呼叫了被代理類
- 實際介面的實現是由被代理類實現的
- 代理類可以在原來的基礎上擴充套件
代理又有靜態代理和動態代理
靜態代理
通過例子來模擬靜態代理
模擬一下,委託別人買票的例子
我有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出來,裡面的方法就是具體代理要做的內容