动态代理在静态代理的基础上提供了在运行时生成代理类的功能。因此相比于静态代理不用自定义代理类了。
用法
interface DemoListener {
fun demo(str: String)
}
class TestDemo : DemoListener {
override fun demo(str: String) {
println(str)
}
}
一个接口,一个实现类,如果使用静态代理还需要创建一个代理类,在代理类中传入实现类,然后进行代理,这样就可以在调用接口方法的前后做一些改变了。
如果是动态代理要怎么做呢?
fun main() {
val testDemo = TestDemo()
val proxy = Proxy.newProxyInstance(
DemoListener::class.java.classLoader,
arrayOf(DemoListener::class.java),
CallBack(testDemo)
) as DemoListener
proxy.demo("345")
}
class CallBack(val any: Any?) : InvocationHandler {
override fun invoke(proxy: Any?, method: Method?, args: Array<out Any>?): Any? {
println("代理前 -------->")
if (any == null) {
return null
}
val invoke = method?.invoke(any, args?.get(0))
println("完成代理 -------->")
return invoke
}
}
动态代理,这种是 java 已经弄好的,只需要调用方法即可。
需要传入参数:classload ,接口 class 的数组,InvocationHandler 的实现。
最终在使用 proxy 调用 demo 方法的时候会执行到 Callback 中的 invoke 方法中。其实 demo 方法还是你自己调用的,只不过用的是反射,好处就是在代理的前后,可以处理一些必须要处理的逻辑。并且可以进行健壮性的判断,例如被代理类是否为 null 等。
使用场景
有些人会动态代理,但是不知道他的使用场景,经常在代码中不知道如果使用,下面说一个非常典型的案例:
在 mvp 中,p 层 和 v 层需要进行交互。但是有一种情况比较棘手,如果 v 层被销毁了,p 层不知道,然后继续调用对应的方法,这种情况下就会导致空指针异常。
解决:使用动态代理,在调用 v 层方法的前面判断一下 v 层是否为空即可
/**
* 动态代理,如果 V 层为 null。则取消调用
*
* @return
*/
@Override
public V getView() {
if (proxy != null) return proxy;
return proxy = (V) Proxy.newProxyInstance(
viewRef.get().getClass().getClassLoader(),
viewRef.get().getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (viewRef.get() != null && isArgs(args)) {
return method.invoke(viewRef.get(), args);
}
return null;
}
其中 viewRef 为弱引用,里面存放着 v 层接口实例。
源码阅读
1,到底干了什么,怎么实现的。
2,学习一些源码怎么写的。
3,如果不懂的代码没必要深究,发现偏了方向赶紧重新回到原点重新来
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
/*
* 生成一个代理类
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
//创建代理类 的构造函数
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//判断如果不是 public 的则设置权限
if (!Modifier.isPublic(cl.getModifiers())) {
cons.setAccessible(true);
// END Android-removed: Excluded AccessController.doPrivileged call.
}
//返回代理类的对象,
return cons.newInstance(new Object[]{
h});
} catch (InvocationTargetException e) {
//........
}
}
上面首先生成了一个代理类,然后就调用代理类的构造,将 InvocationHandler 传了进去
下面看一下代理类是怎样生成的
//代理缓存
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
//获取代理类
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
//从缓存中获取代理
return proxyClassCache.get(loader, interfaces);
}
public V get(K key, P parameter) {
//...
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
//如果获取的是 null,创建一个新的 valuesMap
ConcurrentMap<Object, Supplier<V>> oldValuesMap
= map.putIfAbsent(cacheKey,
valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
//调用 apply 方法生成代理类,subKey 就是代理类
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//从 map 中获取
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
//死循环
while (true) {
if (supplier != null) {
// supplier might be a Factory or a CacheValue<V> instance
V value = supplier.get();
if (value != null) {
return value;
}
}
//创建工厂
if (factory == null) {
factory = new Factory(key, parameter, subKey, valuesMap);
}
//supplier 如果为空,则表示从 map 中没有获取到,下面进行保存
//最终会循环到上面的return ,将 代理类返回出去
if (supplier == null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// successfully installed Factory
supplier = factory;
}
// else retry with winning supplier
} else {
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
} else {
supplier = valuesMap.get(subKey);
}
}
}
}
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
//遍历所有的接口
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
try {
// 加载一个 class
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
//判断 .....
//将 加载出来的 class put 进去
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* 拿到包名
*/
for (Class<?> intf : interfaces) {
//获取修改,判断是否 public
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
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");
}
}
}
if (proxyPkg == null) {
// 如果没有非公共代理接口,则使用默认包。
proxyPkg = "";
}
{
//获取所有方法
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()][]);
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
//代理名称,num 是标志,避免生成名字相同的代理名称
// private static final String proxyClassNamePrefix = "$Proxy";
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// 创建代理类
return generateProxy(proxyName, interfaces, loader, methodsArray,
exceptionsArray);
}
}
}
梳理一下流程:
首先调用 getProxyClass0 方法获取代理类,其中,首先会获取缓存,如果缓存不存在,则创建缓存。接着调用 apply 方法区生产一个代理类,在 apply 方法中会获取到包名,包名则是 proxyPak + $proxy+标志。 获取所有的方法,获取异常等,最终 通过 generateProxy 完成代理class 的床,generateProxy 是 native 层的方法。
拿到 代理后将 InvocationHandler 传入到了代理中,由此我们可以推断 我们调用 newProxyInstance 返回代理类的方法的时候其实调用的就是 InvocationHandler 中的 invoke 方法。在 invoke 中 去反射调用我们需要调用的方法。
总结一下:
动态代理无非就是在程序运行的过程中动态的生成了一个 代理类,这个代理类接收一个接口。
我们在调用 newProxyInstance 方法的时候就会传入一个 实现类。并且返回一个代理类
我们在使用 代理类的时候会将其强转为对应的实现接口。然后在调用对应的方法,其实这里调用的是 实现类的 invoke 方法,在这个方法中去反射调用对应的方法。