動態代理

java實現動態代理的兩種方式
1.jdk動態代理方式,目標對象必須實現了接口,使用反射可生成目標對象的代理類$Proxy0,和目標對象實現了相同的接口;
2.cglib動態代理方式,目標對象沒有實現接口,這時代理對象是目標對象的子類實例。

/**

  • 目標類實現的接口
  • */
    public interface PayService {
    void pay();
    }

/**

  • 業務實現類
  • */
    public class PayServiceImpl implements PayService {

    @Override
    public void pay() {
    System.out.println("支付");
    }

}

/**

  • jdk代理類調用接口中定義的業務方法時,實際調用的是該類的invoke方法
  • */
    public class PayServiceInvocationHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("jdk動態代理 支付前......");
    Object result = method.invoke(target, args);
    System.out.println("jdk動態代理 支付後......");

    return result;

    }

}

/**

  • jdk動態代理
  • */
    public class JdkProxy {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) throws Exception {
    // 代理類 com.sun.proxy.$Proxy0的class文件可以通過下面的配置選項輸出到磁盤上
    System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

    /**
     * 第一種生成代理對象的方法
     * 1.生成InvocationHandler接口的實現類
     * 2.獲取InvocationHandler的構造方法
     * 3.使用constructor生成代理對象
     */
    PayService payService = new PayServiceImpl();
    Class proxyClazz = Proxy.getProxyClass(payService.getClass().getClassLoader(), payService.getClass().getInterfaces());
    Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
    PayService payServiceProxy = (PayService) constructor.newInstance(new PayServiceInvocationHandler(payService));
    payServiceProxy.pay();
    
    /**
     * 第二種生成代理對象的方法
     * 使用Proxy.newProxyInstance()方法
     * 本質上和上面的方法是一致的,只不過是封裝成了一個方法,便於使用
     */
    PayService payServiceProxy2 = (PayService) Proxy.newProxyInstance(payService.getClass().getClassLoader(), payService.getClass().getInterfaces(), new PayServiceInvocationHandler(payService));
    payServiceProxy2.pay();

    }
    }

生成的代理類$Proxy0可通過反編譯查看源碼,如下:
public final class $Proxy0 extends Proxy implements PayService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;

public $Proxy0(InvocationHandler paramInvocationHandler) {
    super(paramInvocationHandler);
}

public final boolean equals(Object paramObject) {
    try {
        return ((Boolean) this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    } catch (Error | RuntimeException localError) {
        throw localError;
    } catch (Throwable localThrowable) {
        throw new UndeclaredThrowableException(localThrowable);
    }
}

/**
 * 接口中的方法 調用此方法,實際是調用InvocationHandler中的invoke()方法 可以在該方法中調用目標方法前後做一些處理,如記錄日誌等。
 */
public final void pay() {
    try {
        this.h.invoke(this, m3, null);
        return;
    } catch (Error | RuntimeException localError) {
        throw localError;
    } catch (Throwable localThrowable) {
        throw new UndeclaredThrowableException(localThrowable);
    }
}

public final String toString() {
    try {
        return (String) this.h.invoke(this, m2, null);
    } catch (Error | RuntimeException localError) {
        throw localError;
    } catch (Throwable localThrowable) {
        throw new UndeclaredThrowableException(localThrowable);
    }
}

public final int hashCode() {
    try {
        return ((Integer) this.h.invoke(this, m0, null)).intValue();
    } catch (Error | RuntimeException localError) {
        throw localError;
    } catch (Throwable localThrowable) {
        throw new UndeclaredThrowableException(localThrowable);
    }
}

static {
    try {
        m1 = Class.forName("java.lang.Object").getMethod("equals",
                new Class[] { Class.forName("java.lang.Object") });
        m3 = Class.forName("test.PayService").getMethod("pay", new Class[0]);
        m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
        m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        return;
    } catch (NoSuchMethodException localNoSuchMethodException) {
        throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    } catch (ClassNotFoundException localClassNotFoundException) {
        throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
}

}

二、cglib動態代理

/**

  • 業務實現類
  • */
    public class PayServiceImpl {
    public void pay() {
    System.out.println("支付");
    }

}

/**

  • cglib代理類的生成方式
  • 1.MethodInterceptor接口的實現類
  • 2.使用Enhancer生成目標對象的子類實例
  • @author Administrator
  • */
    public class PayServiceMethodInterceptor implements MethodInterceptor {
    public Object getInstance() {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(PayServiceImpl.class);
    enhancer.setCallback(this);

    Object proxyObj = enhancer.create();
    
    return proxyObj;

    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    System.out.println("cglib動態代理 支付前");
    Object result = methodProxy.invokeSuper(obj, args);
    System.out.println("cglib動態代理 支付後");

    return result;

    }

}

/**

  • cglib動態代理
  • */
    public class CglibProxy {
    public static void main(String[] args) {
    PayServiceMethodInterceptor payServiceMethodInterceptor = new PayServiceMethodInterceptor();
    PayServiceImpl payServiceImpl = (PayServiceImpl) payServiceMethodInterceptor.getInstance();
    payServiceImpl.pay();
    }
    }

看精彩玄幻世界,盡在《大道揚帆》https://book.qidian.com/info/1012993779

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章