当前位置:阳光沙滩 >Java > 查看文章

1.Java动态代理和静态代理

为什么我们需要用代理呢?

假设一个类,有一个功能,我们要在此功能上进行扩展,又不修改原类。这个时候就可以用代理解决了。具体请看下面的例子。

代理,分为静态代理和动态代理。

2.静态代理

我们举个例子,比如说汽车,它有前进后退,左转右转的功能。

于是我们有一个汽车的功能说明接口,也就是,这是你前辈写的代码,如下:

/**
 * Created by TrillGates on 2018/9/17.
 */

public interface ICarFunction {
    //输出汽车的功能
    void printCardFunction();
}

你的前辈还写了一个实现类,就是CarFunctionImpl

/**
 * Created by TrillGates on 2018/9/17.
 */

public class CarFunctionImpl implements ICarFunction {
    @Override
    public void printCarFunction() {
        System.out.println("前进后退");
        System.out.println("左转右转");
    }
}

好啦,以上就是你的前辈写的,是祖传代码,或者是一个jar包。

但是呢,你的老板要你在这个功能上添加新的功能,比如说,你的汽车可以飞了。所以你要在功能输出里添加飞行的输出

你又不可以改原来的代码,怎么办呢?

这个时候就可以通过代理的方式来解决了。

静态代理的代码怎么写的呢?

第一步:要实现跟被代理类一样的接口

/**
 * Created by TrillGates on 2018/9/17.
 */

public class CarFunctionProxy implements ICarFunction {
    @Override
    public void printCarFunction() {
        
    }
}

这是为什么呢?这样子调用方法还是一样的嘛。你原来调用printCarFunction现在还是一样调用这个方法。

接着,创建被代理的类

/**
 * Created by TrillGates on 2018/9/17.
 */

public class CarFunctionProxy implements ICarFunction {

    CarFunctionImpl mCarFunction = new CarFunctionImpl();

    @Override
    public void printCardFunction() {
        mCarFunction.printCardFunction();
    }
}

到现在,其实功能跟之前是一样的。那有这个必要吗?

当然有,这个时候,我们就可以在 mCarFunction.printCardFunction();的前后添加新的功能了。

比如说

/**
 * Created by TrillGates on 2018/9/17.
 */

public class CarFunctionProxy implements ICarFunction {

    CarFunctionImpl mCarFunction = new CarFunctionImpl();

    @Override
    public void printCardFunction() {
        System.out.println("本汽车有这些功能:");
        mCarFunction.printCardFunction();
        System.out.println("飞行");
    }
}

到此,我们就在原来的基础上添加了新的输出了,没有改变之前的代码,也没有改变调用的方法名称。

所以,对于祖传代码,你想扩展的时候,就可以使用这种代理的方式了。

3.动态代理

动态代理,其实不管是做web开发,还是android开发,学会反射,学会代理可以完成一些不合常理的事情,这一点我深有体会。

一般来说,我们可以使用jdk的InvocationHandler来实现动态代理,也可以使用CGLIB(Code Generation Library)实现动态代理,感兴趣的同学可以研究一下后面这个方法。

我们使用JDK自带的创建代理方式

第一步、还是要有接口,于是我们有了接口:

/**
 * Created by TrillGates on 2018/9/17.
 */

public interface ICarFunction {
    //输出汽车的功能
    void printCardFunction();
}

第二步,被代理的实现类,这个其实已经有了

/**
 * Created by TrillGates on 2018/9/17.
 */

public class CarFunctionImpl implements ICarFunction {
    @Override
    public void printCardFunction() {
        System.out.println("前进后退");
        System.out.println("左转右转");
    }
}

编写一个动态代理类来实现InvocationHandler

/**
 * Created by TrillGates on 2018/9/17.
 */

public class DynamicCarFunctionProxy implements InvocationHandler {
    @Override
    public Object invoke(Object  proxy, Method method, Object[] args) throws Throwable {
        return null;
    }
}

这个invoke,其实就是调用的意思,第一个参数就是被代理的对象,第二个参数就是调用的方法,第三个参数是被调用方法的参数数组。

 


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created by TrillGates on 2018/9/17.
 */

public class DynamicCarFunctionProxy implements InvocationHandler {

    private final ICarFunction carFunction;

    public DynamicCarFunctionProxy(ICarFunction carFunction) {
        this.carFunction = carFunction;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //原方法执行前添加内容
        System.out.println("本汽车有这些功能:");

        // Object invoke = method.invoke(proxy, args);
        //System.out.println("method -- > " + method);
        //System.out.println("args -- > " + args);
        //方法知道了, 反射调用的话,是不是要知道这个方法所在的对象,所以就是传进来的proxy了。
        Object invoke = method.invoke(carFunction, args);
        //执行以后添加的功能
        System.out.println("飞行");
        return invoke;
    }
}

 

调用代码:

/**
 * Created by TrillGates on 2018/9/17.
 */
public class TestMain {

    public static void main(String[] args) {
        CarFunctionImpl carFunction = new CarFunctionImpl();
        DynamicCarFunctionProxy dynamicProxyHandler = new DynamicCarFunctionProxy(carFunction);
        Class[] iCarFunctions = new Class[]{ICarFunction.class};
        ICarFunction carFunctionProxy = (ICarFunction) Proxy.newProxyInstance(CarFunctionImpl.class.getClassLoader(), iCarFunctions, dynamicProxyHandler);
        carFunctionProxy.printCardFunction();
    }
}

测试输出

本汽车有这些功能:
前进后退
左转右转
飞行

那么代理有什么用呢?应用场景有哪些呢?

有卵用….

本文链接:https://blog.sunofbeaches.com/archives/1722 转载请注明出处.
如果喜欢:点此订阅本站
7K
为您推荐
各种观点