静态代理是通过实现类去继承接口并实现接口方法来实现;而动态代理并没有这个实现类,动态代理在运行时通过Proxy.newProxyInstance()去动态创建接口对象,然后去调用接口方法。
通过Proxy.newProxyInstance()创建接口实例,该方法的主要源码如下(有删减),其实就是通过接口类和类加载器获得代理类,通过反射得到代理类的构造函数,进而创建一个对象出来。
/**
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
{
final Class<?>[] intfs = interfaces.clone();
Class<?> cl = getProxyClass0(loader, intfs);
try {
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
cons.setAccessible(true);
}
return cons.newInstance(new Object[]{h});
} catch (Exception e) {}
}
有三个参数
1、ClassLoader loader,可以使用接口类的ClassLoader。
2、Class<?>[] interfaces,需要实现的接口数组,至少要写一个接口类class进去
3、InvocationHandler h,用来处理接口方法调用的InvocationHandler实例。
InvocationHandler实例通过new InvocationHandler()来创建,主要源码如下:
public interface InvocationHandler {
* @param proxy the proxy instance that the method was invoked on
*
* @param method the {@code Method} instance corresponding to
* the interface method invoked on the proxy instance. The declaring
* class of the {@code Method} object will be the interface that
* the method was declared in, which may be a superinterface of the
* proxy interface that the proxy class inherits the method through.
*
* @param args an array of objects containing the values of the
* arguments passed in the method invocation on the proxy instance,
* or {@code null} if interface method takes no arguments.
* Arguments of primitive types are wrapped in instances of the
* appropriate primitive wrapper class, such as
* {@code java.lang.Integer} or {@code java.lang.Boolean}.
*
* @return the value to return from the method invocation on the
* proxy instance. If the declared return type of the interface
* method is a primitive type, then the value returned by
* this method must be an instance of the corresponding primitive
* wrapper class; otherwise, it must be a type assignable to the
* declared return type. If the value returned by this method is
* {@code null} and the interface method's return type is
* primitive, then a {@code NullPointerException} will be
* thrown by the method invocation on the proxy instance. If the
* value returned by this method is otherwise not compatible with
* the interface method's declared return type as described above,
* a {@code ClassCastException} will be thrown by the method
* invocation on the proxy instance.
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
invoke(Object proxy, Method method, Object[] args)第一个参数表示之前Proxy.newProxyInstance()创建的接口实例,第二个参数表示调用的接口方法,最后一个参数表示接口方法的参数。在invoke中处理方法逻辑,这也是面向切面编程的地方。
创建接口实例和InvocationHandler实例后,将Object类型的接口实例强制转为接口类型,然后调用接口方法,然后在InvocationHandler实例的invoke方法中处理自己的业务逻辑即可。
demo如下:
public void TestProxy(View view) {
InvocationHandler invocationHandler=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Log.d(TAG, "invoke: method="+method);
if (method.getName().equals("study")) {
Log.d(TAG, "invoke: "+args[0]+" is study");
}
return null;
}
};
IPersion developer = (IPersion) Proxy.newProxyInstance(IPersion.class.getClassLoader(),new Class[]{IPersion.class},invocationHandler);
developer.study("developer");
}
点击view后log打印如下:
2020-01-27 21:11:52.922 21127-21127/com.example.myapplication D/MainActivityLog: invoke: method=public abstract void com.example.myapplication.IPersion.study(java.lang.String)
2020-01-27 21:11:52.922 21127-21127/com.example.myapplication D/MainActivityLog: invoke: developer is study