为了理解动态代理先说下静态代理,很简单的一个例子:
一个接口:
public interface ServiceApi {
void showMessage(String msg);
}
一个实现接口的一个具体实现类:
public class ServiceApiImpl implements ServiceApi {
@Override
public void showMessage(String msg) {
System.out.println(msg);
}
}
一个代理类:
public class ServiceApiAgent implements ServiceApi {
private ServiceApiImpl serviceApi;
public ServiceApiAgent(ServiceApiImpl serviceApi) {
this.serviceApi = serviceApi;
}
@Override
public UserInfo showMessage(String msg) {
System.out.println("静态代理开始前--------");
UserInfo userInfo = serviceApi.showMessage(msg);
System.out.println("静态代理结束后--------");
return userInfo;
}
}
一个测试方法来调用:
@Test
public void testAgent() {
ServiceApiImpl impl = new ServiceApiImpl();
ServiceApiAgent serviceApiAgent = new ServiceApiAgent(impl);
serviceApiAgent.showMessage("我是静态代理方法来的参数");
}
运行结果:
静态代理开始前--------
我是静态代理方法来的参数
静态代理结束后--------
Process finished with exit code 0
可能有疑问:1、一个接口而已,直接new出来具体的实现类ServiceApiImpl ,然后调用showMessage就行了,为什么会多此一举再加一个ServiceApiAgent ?目的是为了能增强代码,例如我们需要在实现接口的前后都记录一下我们的操作日志,这样就可以直接在代理类中实现,而不是直接在用的地方添加。2、为啥代理类也需要实现这个接口?还是以第一点为主,代理类是增强代码为主,具体的实现功能和被代理类是一致的,如果不一致,就失去了代理的意义。
但是这样就会产生一个问题,代码中大量的接口怎么办?我们需要new出来大量的代理类,显然比较累人。很容易看到,代理类和被代理类都有一个共同的类信息,那就是接口类(ServiceApi .java),如果不创建代理类,直接通过接口类ServiceApi 产生一个代理类的对象,是不是就可以去调用接口类里面的方法了?答案是可以的,JDK提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类,这两个类相互配合,入口是Proxy。注意:是通过接口类去生成一个代理类,紧接着上面的代码改造一下:
ServiceApi serviceApi = (ServiceApi) Proxy.newProxyInstance(ServiceApi.class.getClassLoader(), new Class<?>[] { ServiceApi.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
System.out.println("动态代理开始前--------");
return method.invoke(impl,args);
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println("动态代理结束后--------");
}
return null;
}
});
serviceApi.showMessage("我是动态代理方法来的参数");
运行结果:
动态代理开始前--------
我是动态代理方法来的参数
动态代理结束后--------
Process finished with exit code 0
这段代码的理解:先看下newProxyInstance方法干了什么,源码中是这样的
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
// Android-removed: SecurityManager calls
/*
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
*/
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
// Android-removed: SecurityManager / permission checks.
/*
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
if (!Modifier.isPublic(cl.getModifiers())) {
// BEGIN Android-changed: Excluded AccessController.doPrivileged call.
/*
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
*/
cons.setAccessible(true);
// END Android-removed: Excluded AccessController.doPrivileged call.
}
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
很简单,就是对我们的接口类ServiceApi 先进行了一次浅拷贝interfaces.clone();接着getProxyClass0(loader, intfs)获取了一个class,接着就是对class获取了一个构造方法getConstructor,然后对构造方法newInstance,就生成了一个对象,(java的jvm类构造器相当变态,这都可以。。。),此时的代理类对象就生成了,就是我们上面代码中的serviceApi 对象。还有一个参数InvocationHandler ,是一个回调对象,当我们调用接口类方法的时候就会执行InvocationHandler 里面的invoke方法。
通俗的理解就是以接口class生成代理class,借助之前看到的一片文章的比喻形象的说明一下过程就是:西厂公公(ServiceApi)很强大,文武双全但是他净身了(就是没有构造器),本领无法发扬光大。想办法:
1、通过正常途径(implements):抓一个骨骼奇异之人,身心俱全(有构造器,就是我们具体的实现接口的类)的回来,让他学习继承本领。
2、不正常途径(动态代理):西域高僧(Proxy)取他一滴精血克隆一个身心俱全(浅拷贝interfaces.clone(),有构造器)的Class出来,并且这个class还可以实例化对象出来。
将动态代理再优化一下:参照Retrofit的实现
@SuppressWarnings("unchecked")
public <T> T create(Class<T> service) {
validateServiceInterface(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//此处添加我们自己的业务逻辑实现代码
ApiMethod apiMethod = new ApiMethod();
return apiMethod.invoke(args);
}
});
}
private <T> void validateServiceInterface(Class<T> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
// Prevent API interfaces from extending other interfaces. This not only avoids a bug in
// Android (http://b.android.com/58753) but it forces composition of API declarations which is
// the recommended pattern.
if (service.getInterfaces().length > 0) {
throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
}
}
在使用的地方调用代码:
ServiceApi serviceApi = create(ServiceApi.class);