Java动态代理和静态代理
为什么我们需要用代理呢?
假设一个类,我们不想别人使用它里面的所有功能,或者部分功能,我们就可以通过代理的方式管理了。
代理,分为静态代理和动态代理。
静态代理
我们举个例子,比如说汽车,它有前进后退,左转右转的功能。
于是我们有一个汽车的功能说明接口,也就是,这是你前辈写的代码,如下:
/**
* 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("飞行");
}
}
到此,我们就在原来的基础上添加了新的输出了,没有改变之前的代码,也没有改变调用的方法名称。
所以,对于祖传代码,你想扩展的时候,就可以使用这种代理的方式了。
动态代理
动态代理,其实不管是做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();
}
}
测试输出
本汽车有这些功能:
前进后退
左转右转
飞行
那么代理有什么用呢?应用场景有哪些呢?评论区吧!