設計模式:動態代理

guojunjiang12345發表於2020-10-15

序言

動態代理,是十分常見的,Spring著名的AOP就是基於動態代理實現的,今天我們來學習一下動態代理叭。

代理

代理可以分為兩大類:動態代理和靜態代理

區別:靜態代理在編譯時增強,動態代理在執行時增強

靜態代理的CODE

//介面:
interface Teacher{
    void teach();
}
//介面的實現:
class GoodTeacher implements Teacher{
    @Override
    public void teach() {
        System.out.println("老師教書");
    }
}
//代理類
class TeacherProxy implements Teacher{
    private Teacher teacher;
    TeacherProxy(Teacher teacher){
        this.teacher=teacher;
    }
    @Override
    public void teach() {
        System.out.println("靜態代理開始");
        teacher.teach();
        System.out.println("代理結束");
    }
}

動態代理

動態代理也可以分為兩種:JDK動態代理和CgLib動態代理

區別:

  • JDK動態代理依賴於介面,被代理的類必須實現介面
  • CgLib動態代理不依賴於介面
  • JDK在建立物件速度快,執行時速度慢,CgLib建立物件速度慢,執行速度快

JDK動態代理

class ProxyTeacher2{
    private GoodTeacher goodTeacher=null;
    ProxyTeacher2(GoodTeacher goodTeacher){
        this.goodTeacher=goodTeacher;
    }
    //生成goodTeacher的代理物件
    public Teacher getProxy(){
       return (Teacher) Proxy.newProxyInstance(goodTeacher.getClass().getClassLoader(), goodTeacher.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object invoke = method.invoke(goodTeacher,args);
                System.out.println("動態代理增強方法體");
                return invoke;
            }
        });
    }
}

CgLib動態代理

class Ogn{
    public void buy(int money){
        System.out.println("真實物件獲取到了"+money);
    }
}
public class CgLibProxy {
    public static void main(String[] args) {
        Ogn ogn=new Ogn();
        Ogn DL=(Ogn)Enhancer.create(ogn.getClass(), new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                if(method.getName().equals("buy")){
                    int i=(Integer)args[0];
                    i*=0.8;
                    Object invoke = method.invoke(ogn, i);
                    return invoke;
                }
                return method.invoke(ogn,args);
            }
        });
        DL.buy(1000);
    }
}

需要注意的是使用CgLib需要引入Cglib的jar包

結束

動態代理還是很常見的,很多框架中都是用到了動態代理,所以我們有必要了解掌握動態代理模式

相關文章