java代理模式简单实现

论坛 期权论坛 脚本     
匿名技术用户   2020-12-22 06:02   75   0

静态代理(编译时)实现:

package StaitcProxy;

/**
 * Created by N3verL4nd on 2017/3/24.
 */
public interface ArithmeticCalculator {
    int add(int x, int y);
    int sub(int x, int y);
    int mul(int x, int y);
    int div(int x, int y);
}
package StaitcProxy;


/**
 * Created by N3verL4nd on 2017/3/24.
 */
public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
    @Override
    public int add(int x, int y) {
        int result = x + y;
        return result;
    }

    @Override
    public int sub(int x, int y) {
        int result = x - y;
        return result;
    }

    @Override
    public int mul(int x, int y) {
        int result = x * y;
        return result;
    }

    @Override
    public int div(int x, int y) {
        int result = x / y;
        return result;
    }
}
package StaitcProxy;

/**
 * Created by N3verL4nd on 2017/3/25.
 */
public class StaticProxy implements ArithmeticCalculator {
    private ArithmeticCalculator calculator; //被代理的对象

    public StaticProxy(ArithmeticCalculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public int add(int x, int y) {
        System.out.println("The method [add] begins");
        int result = calculator.add(x, y);
        System.out.println("The method [add] ends");
        return result;
    }

    @Override
    public int sub(int x, int y) {
        System.out.println("The method [sub] begins");
        int result = calculator.sub(x, y);
        System.out.println("The method [sub] ends");
        return result;
    }

    @Override
    public int mul(int x, int y) {
        System.out.println("The method [mul] begins");
        int result = calculator.mul(x, y);
        System.out.println("The method [mul] ends");
        return result;
    }

    @Override
    public int div(int x, int y) {
        System.out.println("The method [div] begins");
        int result = calculator.div(x, y);
        System.out.println("The method [div] ends");
        return result;
    }
}
package StaitcProxy;

/**
 * 为其他对象提供一种代理以控制对这个对象的访问。
 * 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
 * 其特征是代理类与委托类有同样的接口
 * 我们可以借助代理类增加一些功能,而不需要修改原有代码。而真正的业务逻辑还是由委托类(被代理对象)实现。
 * Created by N3verL4nd on 2017/3/25.
 */
public class Main {
    public static void main(String[] args) {
        ArithmeticCalculator calculator = new ArithmeticCalculatorImpl();

        ArithmeticCalculator proxy = new StaticProxy(calculator);
        int result = proxy.add(10 ,20);
        System.out.println("result = " + result);
    }
}

1.使用组合。

2.需要实现相同的接口。

动态代理(运行时,通过反射实现)实现:

public interface InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable;
}

proxy:被代理的对象

method:要调用的方法

args:方法调用时所需要的参数

即调用proxy对象的method方法,传入参数为args。

public static Object newProxyInstance(ClassLoader loader,
                                      Class<?>[] interfaces,
                                      InvocationHandler h)
    throws IllegalArgumentException
{}

loader:类加载器

interfaces:得到全部的接口

h:得到InvocationHandler接口的子类

public Object invoke(Object obj, Object... args)
    throws IllegalAccessException, IllegalArgumentException,
       InvocationTargetException
{}

Object result = method.invoke(target, args);

执行target对象中带有参数args的method方法。返回值是Object,也既是该方法的返回值。

package DynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;

/**
 * Created by N3verL4nd on 2017/3/25.
 */
public class DynamicProxy implements InvocationHandler {
    private Object target;

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

    public Object getInstance() {
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                this
        );
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(proxy.getClass().getName());

        System.out.println("The method [" + method.getName() + "] begins with " + Arrays.toString(args));

        Object result = method.invoke(target, args);

        System.out.println("The method [" + method.getName() + "] ends with " + result);

        return result;
    }
}

package DynamicProxy;


/**
 * Created by N3verL4nd on 2017/3/25.
 */
public class Main {
    public static void main(String[] args) {
        ArithmeticCalculator calculator = new ArithmeticCalculatorImpl();
        DynamicProxy dynamicProxy = new DynamicProxy(calculator);

        ArithmeticCalculator calculatorProxy = (ArithmeticCalculator) dynamicProxy.getInstance();
        calculatorProxy.add(10, 20);
        /*calculatorProxy.sub(10, 20);
        calculatorProxy.mul(10, 20);
        calculatorProxy.div(10, 20);*/
    }
}

CGLib实现(借助asm实现):

Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类没有实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理:

net.sf.cglib.proxy.Enhancer – 主要的增强类
net.sf.cglib.proxy.MethodInterceptor – 主要的方法拦截类,它是Callback接口的子接口,需要用户实现
net.sf.cglib.proxy.MethodProxy – JDK的java.lang.reflect.Method类的代理类,可以方便的实现对源对象方法的调用

如使用:
Object o = methodProxy.invokeSuper(proxy, args);//虽然第一个参数是被代理对象,也不会出现死循环的问题。
net.sf.cglib.proxy.MethodInterceptor接口是最通用的回调(callback)类型,它经常被基于代理的AOP用来实现拦截(intercept)方法的调用。这个接口只定义了一个方法
public Object intercept(Object object, java.lang.reflect.Method method,
Object[] args, MethodProxy proxy) throws Throwable;


第一个参数是代理对像,第二和第三个参数分别是拦截的方法和方法的参数。原来的方法可能通过使用java.lang.reflect.Method对象的一般反射调用,或者使用 net.sf.cglib.proxy.MethodProxy对象调用。net.sf.cglib.proxy.MethodProxy通常被首选使用,因为它更快。

package CGLibProxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * Created by N3verL4nd on 2017/3/25.
 */
public class CGLibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("The method " + method.getName() + " begins with " + Arrays.toString(args));

        Object result = methodProxy.invokeSuper(obj, args);

        System.out.println("The method ends with " + result);
        return result;
    }
}

package CGLibProxy;

import net.sf.cglib.proxy.Enhancer;

/**
 * Created by N3verL4nd on 2017/3/25.
 */
public class Main {
    public static void main(String[] args) {
        CGLibProxy cgLibProxy = new CGLibProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(ArithmeticCalculatorImpl.class);
        enhancer.setCallback(cgLibProxy);

        ArithmeticCalculator calculator = (ArithmeticCalculator) enhancer.create();
        calculator.add(10, 20);

    }
}

参考:

http://blog.csdn.net/wangyongxia921/article/details/46124197

http://blog.csdn.net/heyutao007/article/details/49738887

https://my.oschina.net/Thehope/blog/856875?nocache=1490407597955

http://blog.csdn.net/dreamrealised/article/details/12885739

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP