动态代理
- 静态代理:在代码运行之前代理类的class文件就存在了
- 动态代理:刚刚相反,通过反射来动态生成代理对象,也就是说编码的时候不知道代理谁,只有执行的时候才知道。
我们还用上个月静态代理的例子来说明
地址:https://livesun.github.io/2017/06/19/Proxy_Mode/
/**
* Created by 29028 on 2017/6/19.
*
* 自己的接口
*/
public interface ISlef {
//我能干什么
//吃
public void eat();
//工作
public void doWork();
}
创建被代理类,我们自己。
/**
* Created by 29028 on 2017/6/19.
* 真的自己
*/
public class TrueSelf implements ISlef {
private ISlef slef;
//默认让一号来
public TrueSelf(){
slef =new ProxyRobot1();
}
//设置替身 我想谁几号替我就让几号来
public void setProxy(ISlef slef){
this.slef = slef;
}
//吃东西这事还是我们自己来比较好
public void eat() {
Log.d("AAA","我悠哉悠哉的吃肉");
}
public void doWork() {
slef.doWork();
}
}
如果按照静态代理,我们必须写这个替身一号的代理类
/**
* Created by 29028 on 2017/6/19.
* 机器人替身1号 我会的他也会
*/
public class ProxyRobot1 implements ISlef {
public void eat() {
Log.d("AAA","机器人替身1号吃电");
}
public void doWork() {
Log.d("AAA","机器人替身1号帮我做工作");
}
}
然后这样,让代理类帮我们做事情
private void doThings() {
TrueSelf self=new TrueSelf();
self.doWork();
self.eat();
}
这里面可以看到,其实我们必须要创建ProxyRobot1机器人一号,来代理我们做事情,如果有很多方法,那会很麻烦,尤其是如果运用在MVP架构中,我们每个方法基本都要判断ISlef为不为空,基于如此,所以动态代理应运而生。
Java其实已经帮我们封装了动态代理的方法,我们只需要Proxy这个类,以及实现InvocationHandler接口,并调用invoke即可。
代码如下
/**
* 真的自己
*/
public class TrueSelf implements ISlef {
//吃东西这事还是我们自己来比较好
public void eat() {
Log.d("AAA","我悠哉悠哉的吃肉");
}
public void doWork() {
Log.d("AAA","我的工作做完了");
}
}
private void doThings() {
TrueSelf self=new TrueSelf();
ISlef proxy = (ISlef) Proxy.newProxyInstance(
self.getClass().getClassLoader(),
self.getClass().getInterfaces(),
new MyInvocationHandler(self)
);
proxy.eat();
proxy.doWork();
}
public class MyInvocationHandler implements InvocationHandler{
private ISlef man;
public MyInvocationHandler(ISlef man) {
this.man = man;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.d("AAA","机器人帮我干货");
Object obj=method.invoke(man,args);
return obj;
}
}
可以看到,我们并没有创建ProxyRobot1代理类,但同样完成了之前的工作。
使用是非常简单的
接着粗略的看下Proxy的源码是如何实现动态代理的。
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interface,InvocationHandler h)
throws IllegalArgumentException
{
Class<?> cl = getProxyClass0(loader, interfaces);
//调用InvocationHandler的构造函数,其实就是每次调用newProxyInstance,就去执行了InvocationHandler里面的那个invoke方法。
final Constructor<?> cons = cl.getConstructor(constructorParams);
return newInstance(cons, h);
}
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
Class<?> proxyClass = null;
String[] interfaceNames = new String[interfaces.length];
Set<Class<?>> interfaceSet = new HashSet<>();
for (int i = 0; i < interfaces.length; i++) {
//获取所有接口的名字
String interfaceName = interfaces[i].getName();
Class<?> interfaceClass = null;
try {
//获取所有接口
interfaceClass = Class.forName(interfaceName, false, loader);
} catch (ClassNotFoundException e) {
}
interfaceSet.add(interfaceClass);
interfaceNames[i] = interfaceName;
}
try {
String proxyPkg = null;
for (int i = 0; i < interfaces.length; i++) {
int flags = interfaces[i].getModifiers();
if (!Modifier.isPublic(flags)) {
//获取完整的比如 livesun.proxy.test.Iself
String name = interfaces[i].getName();
int n = name.lastIndexOf('.');
//pak=livesun.proxy.test. 获取包名
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
//获取接口里面所有的方法
List<Method> methods = getMethods(interfaces);
//把这些方法经行排序
Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
validateReturnTypes(methods);
//抛异常的方法
List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
Method[] methodsArray = methods.toArray(new Method[methods.size()]);
Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
final long num;
synchronized (nextUniqueNumberLock) {
num = nextUniqueNumber++;
}
//private final static String proxyClassNamePrefix = "$Proxy"; 解析interface所有的方法,新建一个class,这个类的名字为,包名+$Proxy。livesun.proxy.test.$Proxy
String proxyName = proxyPkg + proxyClassNamePrefix + num;
proxyClass = generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
//proxyClass类
return proxyClass;
}
//native方法,其实就是生成proxyClass类(具体内部的实现,其实并不懂。。。)
private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
ClassLoader loader, Method[] methods,
Class<?>[][] exceptions);