天天看點

WHWW之代理模式(3)-cglib動态代理

What:什麼是cglib動态代理?

cglib動态代理是由第三方類庫實作的代理,使用要添加cglib jar包,其代理底層是借助 asm來實作的。( asm是java虛拟機裡面的一種動态生成位元組碼的技術,跟反射是不同的)

How:怎麼實作cglib動态代理呢?

/**
 * 目标對象類
 */
public class Target {
    public void sayHello() {
        System.out.println("你好");
    }
}
      
/**
 * cglib動态代理
 */

public class CGLibDynamicProxy implements MethodInterceptor {

    //目标對象
    private  Object target;

    /**
     * 建立代理對象
     * @param target
     * @return
     */
    public Object getInstance(Object target){
        this.target=target;

        //用這個類 來建立代理對象(被代理類的子類);并設定父類;設定回調。
        //Enhancer該類是cglib jar包中的類
        Enhancer enhancer=new Enhancer();

        //設定被代理類作為其父類的代理目标
        enhancer.setSuperclass(this.target.getClass());

        //設定回調方法,當這個代理對象方法被調用時,回調方法intercept()會被執行
        enhancer.setCallback(this);

        //傳回建立的代理對象
        return enhancer.create();
    }

    /**
     * 回調方法
     * @param o
     * @param method
     * @param objects
     * @param methodProxy 代理的類的方法(會調用父類被代理的方法)
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result=null;
        before();//前置增強
        result=methodProxy.invokeSuper(o,objects);
        after();//後置增強

        return result;
    }

    /**
     * 在實作方法前可以做的事情
     */
    public  void  before(){
        System.out.println("摘下耳機");
    }

    /**
     * 在實作方法後做的事情
     */
    public void after(){
        System.out.println("戴上耳機");
    }

}
      
/**
 * cglib動态代理測試端
 */
public class CglibProxyTest {

    public static void main(String[] args) {
        CGLibDynamicProxy cgLibDynamicProxy=new CGLibDynamicProxy();
        //生成代理對象
        Target hello=(Target) cgLibDynamicProxy.getInstance(new Target());
        //當調用代理對象的被代理方法時,會自動回調,調用CGLibDynamicProxy代理類中的Intercept()方法
        hello.sayHello();

    }
}
      

控制台輸出:

摘下耳機

你好

戴上耳機

Process finished with exit code 0

Why:為什麼要用cglib動态代理?

因為jdk動态代理隻能代理實作了接口的類,如果該目标類沒有實作任何接口,則不能使用jdk動态代理,可以看下WHWW之代理模式(2)-動态代理。而cglib動态代理是針對類來實作的,也就是說這個目标類可以不用實作任何接口,cglib動态代理都可以對該類進行代理。

注:因為cglib動态代理采用的是繼承,是以不能對final修飾的類進行代理

Where:哪些地方使用cglib動态代理?

spring Aop的底層實作就用到cglib動态代理,如果我們要對沒有實作接口的類進行功能擴充時,也可以考慮cglib動态代理。

繼續閱讀