静态代理和动态代理

在插件化技术中,很多功能的实现都使用的动态代理技术,比如VirtualAPK中的替换Service组件的实现就是使用的动态代理,Retrofit里面也使用到动态代理技术来获取接口类的对象,具体的可以看我之前的文章Retrofit的简单使用和源码分析, 如果你还不太清除静态代理和动态代理,就看看今天的文章吧。

静态代理

指的是代理类在程序运行之前就已经写好了,通过代理类可以调用到目标类中实现的功能代码,代理类和目标类通过集成相同的接口来做到功能的一致性,同时通过代理类也能够对目标类做对应的功能扩展,扩展的过程中做到不破坏目标类的代码结果。

//代理接口
public interface IUser {
	String getUser();
}
//目标类
public class User implements IUser{
	@Override
	public String getUser() {
		String name = "Mr zhang";
		return name;
	}
}
//代理类
public class ProxyUser implements IUser{
	private User user;
	public ProxyUser() {
		user = new User();
	}
	@Override
	public String getUser() {
		System.out.print("获取后。。。");
		String name = user.getUser();
		System.out.print("获取后。。。");
		return name;
	}
}

可以看到在代理类里面实际调用的是目标类的方法,在需要扩展的时候,我们不需要修改目标类,直接在代理类里面进行扩展就可以。

但是静态代理的缺点是,需要为每个目标类创建代理类和接口,工作量大;接口功能一旦修改,代理类和目标类也得相应修改,不易维护,这时候就出现了动态代理。

动态代理

在代码的运行的过程中动态生成代理类,然后通过反射的方式调用目标类的方法。好处是不用为每个目标类都编写一个对应的代理类,只需要提供目标类就可以动态的生成代理类。

拿Java中提供的动态代理的类Proxy来说,具体的使用流程看下面的例子。

//代理接口
public interface IUser {
    String getUser();
}
//目标类
public class User implements IUser{

	@Override
	public String getUser() {
		String name = "Mr zhang";
		return name;
	}

}
//获取代理对象
public static Object getProxy(User user){
		ClassLoader classLoader = IUser.class.getClassLoader();
		Class[] clazz = new Class[]{IUser.class};
		Object proxyInstance = Proxy.newProxyInstance(classLoader,clazz,new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println("方法名:" + method.getName());
				Object invoke = method.invoke(user, args);	
				return invoke;	
			}
		});
		return proxyInstance;
	}

public static void main(String[] args){
 	IUser user = (IUser) getProxy(new User());
	String name = user.getUser();
	System.out.println("name::" + name);
}
//执行结果:
方法名:getUser
name::Mr zhang

看上面的代码,我们只需要传入目标类的对象就能获取到对应的代理对象,就不用针对每一个目标类创建一个代理类了,它的实现原理就是通过反射的方式调用目标类的方法,如果你去看上面的Proxy的源码,也是使用反射的方式来完成调用的,好处是在代码运行当中就可以拦截方法,可以在调用方法的前后做一些事情,比如在invoke方法中可以获得到getUser方法的各种信息,包括Method对象、参数args,在这里相当于对接口中的方法进行了拦截可以做一些扩展操作。

相对于静态代理,极大的减少类的数量,降低工作量,减少对业务接口的依赖,降低耦合,便于后期维护。因为使用的是反射,所以在运行时会消耗一定的性能。

参考链接:https://mp.weixin.qq.com/s/dSt4ifbAaRxPAc7gCAVxoA

最后欢迎关注我的公众号,谢谢。

在这里插入图片描述

关注我的公众号,我们一起进步

你可能感兴趣的:(插件化)