動(dòng)態(tài)代理

Jdk 動(dòng)態(tài)代理

Jdk動(dòng)態(tài)代理,利用反射,實(shí)現(xiàn) InvocationHandler 接口。Jdk 動(dòng)態(tài)代理需要實(shí)現(xiàn)類(lèi)通過(guò)接口定義業(yè)務(wù)方法,也就是說(shuō),委托類(lèi)必須實(shí)現(xiàn)一個(gè)定義了業(yè)務(wù)方法的接口,在接口里約定需要代理的方法,并且只能對(duì)接口里約定的方法實(shí)現(xiàn)代理。由于需要委托類(lèi)實(shí)現(xiàn)一個(gè)接口,這是一個(gè)局限性。

Jdk 代理類(lèi)圖
  • Subject 類(lèi)
public interface Subject {
    void doSomething();
}
  • RealSubject 類(lèi)
public class RealSubject implements Subject {
    @Override
    public void doSomething() {
        System.out.println("do something");
    }
}
  • Jdk 代理
public class JdkProxy implements InvocationHandler {
    private Object target;

    public JdkProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result;
        System.out.println("jdk proxy before");
        result = method.invoke(target, args);
        System.out.println("jdk proxy after");
        return result;
    }
}
  • Jdk 代理測(cè)試
public class JdkProxyTest {
    @Test
    public void testJdkProxy() {
        RealSubject realSubject = new RealSubject();
        Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new JdkProxy(realSubject));
        subject.doSomething();
    }
}

運(yùn)行結(jié)果:
jdk proxy before
do something
jdk proxy after

Cglib 動(dòng)態(tài)代理

Cglib 代理是針對(duì)類(lèi)來(lái)實(shí)現(xiàn)代理的,并不要求委托類(lèi)必須實(shí)現(xiàn)接口,它的原理是對(duì)指定的目標(biāo)類(lèi)生成一個(gè)子類(lèi),并覆蓋其中方法實(shí)現(xiàn)增強(qiáng),采用的是繼承的方式。由于是采用繼承的方式,所以用 Cglib 實(shí)現(xiàn)的代理類(lèi)是不能處理被final關(guān)鍵字修飾的方法的。

Cglib 代理類(lèi)圖
  • Cglib 代理
public class CglibProxy implements MethodInterceptor {
    public Object getInstance(Class clazz) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result;
        System.out.println("cglib proxy before");
        result = methodProxy.invokeSuper(o, objects);
        System.out.println("cglib proxy after");
        return result;
    }
}

在上文中可以看到,代理對(duì)象的生成過(guò)程是由 Enhancer 類(lèi)來(lái)實(shí)現(xiàn)的,大概步驟是:

  1. 生成代理類(lèi) Class 的二進(jìn)制字節(jié)碼;
  2. 通過(guò) Class.forName 加載二進(jìn)制字節(jié)碼,生成Class對(duì)象;
  3. 通過(guò)反射機(jī)制獲取實(shí)例構(gòu)造,并初始化代理類(lèi)對(duì)象。

intercept() 方法攔截目標(biāo)類(lèi)方法的調(diào)用,o 表示目標(biāo)類(lèi)的實(shí)例,method 為目標(biāo)類(lèi)方法的反射對(duì)象,objects 為方法的動(dòng)態(tài)入?yún)?,methodProxy 為代理類(lèi)實(shí)例。

  • Cglib 代理測(cè)試
public class CglibProxyTest {
    @Test
    public void testCglibProxy() {
        RealSubject realSubject = (RealSubject) new CglibProxy().getInstance(RealSubject.class);
        realSubject.doSomething();
    }
}

運(yùn)行結(jié)果:
cglib proxy before
do something
cglib proxy after

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容