我们先看下静态代理,具体方法就是创建一个接口,然后创建被代理的类实现该接口并且实现该接口中的抽象方法。之后再创建一个代理类,同时也需要实现这个接口。在代理类中会持有一个被代理对象的引用,而后在代理类方法中调用该对象的方法。静态代理被代理类和代理类是一对一的关系,这就造成了如果需要被代理的类多了,那相应的代理类也会很多,那这就很不程序猿了。这时候动态代理就粗线了(此处有掌声),和静态代理相比,动态代理就是代理类这块由系统通过底层反射的方式帮我们生成了(这就很程序猿了),但是和静态的思路是一样的,具体看一下静态代理的例子
先创建一个接口
String buy();
}
搞两个被代理的类,继承这个接口
public class ZhangSan implements IBuySth {
@Override
public String buy() {
System.out.println("我张三要买东西的");
return "";
}
}
public class LiSi implements IBuySth {
@Override
public String buy() {
System.out.println("我李四要买东西的");
return "";
}
}
然后我们就可以搞个代理类了
public class Seller implements IBuySth {
IBuySth iBuySth;
public Seller(IBuySth iBuySth) {
this.iBuySth = iBuySth;
}
@Override
public String buy() {
System.out.println("Before buy " );
iBuySth.buy();
System.out.println("After buy " );
return "";
}
}
我们去调用一下这个代理类
IBuySth san=new ZhangSan();
Seller seller=new Seller(san);
seller.buy();
我们看一下结果,是没问题的。-代理模式就是自己要做的事,通过其他实现相同接口的类去代替完成-,就是这么个意思。
image.png
静态代理完了,再看一下我们的动态代理类,这个类首先要传入被代理对象,这里用object就可以,然后要实现的就是InvocationHandler这个接口,通过这个接口重载的invoke方法,在这个方法里我们可以在调用被代理对象之前和之后做一些方法,这也是动态代理的优势可扩展性,然后调用method方法的invoke,其实这个底层就是用的反射的方式去获取被代理对象的那个buy方法,然后对外部暴露一个getInstance方法,这个写在外边也ok的,这个方法主要是通过Proxy这个类去反射出我们的代理类,如果打断点就会发现其实就是Proxy1这些系统帮我们生成的代理类。
public class MyProxy implements InvocationHandler {
Object obj;
public MyProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before invoke " + method.getName());
method.invoke(obj,args);
System.out.println("After invoke " + method.getName());
return null;
}
public Object getInstance(){
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
}
最后我们可以去调用一下了
IBuySth san=new ZhangSan();//此处改外new LiSi则调用的被代理对象就是李四了
MyProxy myProxy=new MyProxy(san);
Proxy.newProxyInstance(san.getClass().getClassLoader(), san.getClass().getInterfaces(), handler);
IBuySth s= (IBuySth) myProxy.getInstance();
s.buy();
可以看到和静态代理结果是一样的
image.png
动态代理被广泛的用在各种框架中,虽然我们代码中遇到的少,但是还是要掌握的,比如Retrofit的 cteate方法中,可以看到就是用到了动态代理的方法去实现的。
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() { //动态代理的方法去实现的
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, Object... args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
网友评论