爲其餘對象提供一種代理以控制對這個對象的訪問bash
主要做用:控制對象訪問網絡
編譯時期就已經存在,通常首先須要定義接口,而被代理的對象和代理對象一塊兒實現相同的接口。ide
public interface Play {
//唱歌
void sing(int count);
//演出
void show();
}
複製代碼
public class Actor implements Play {
@Override
public void sing(int count) {
System.out.print("唱了" + count + "首歌");
}
@Override
public void show() {
System.out.print("進行演出");
}
}
複製代碼
被代理對象提供了幾個具體方法實現post
public class Agent implements Play {
//被代理對象
private Play player;
private long money;
public void setMoney(long money){
this.money = money;
}
/**
* @param player
* @param money 收費
*/
public Agent(Play player, long money) {
this.player = player;
this.money = money;
}
@Override
public void sing(int count) {
player.sing(count);
}
//控制了被代理對象的訪問
@Override
public void show() {
if (money > 100) {
player.show();
} else {
System.out.println("baibai...");
}
}
}
複製代碼
public class PlayTest {
public static void main(String[] args){
Actor actor = new Actor();
Agent agent = new Agent(actor, 50);
agent.sing(2);
agent.show();
agent.setMoney(200);
agent.show();
}
}
複製代碼
代理對象經過自身的邏輯處理對目標對象的功能進行控制。ui
動態通常指的是在運行時的狀態,是相對編譯時的靜態來區分,就是在運行時生成一個代理對象幫咱們作一些邏輯處理。主要使用反射技術得到類的加載器而且建立實例。
動態代理能夠在運行時動態建立一個類,實現一個或多個接口,能夠在不修改原有類的基礎上動態爲經過該類獲取的對象添加方法、修改行爲。this
InvocationHandler是動態代理接口,動態代理類須要實現該接口,並在invoke方法中對代理類的方法進行處理spa
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
複製代碼
參數說明:插件
Proxy類能夠經過newProxyInstance建立一個代理對象代理
#Proxy
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
if (h == null) {
throw new NullPointerException();
}
Class<?> cl = getProxyClass0(loader, interfaces);
try {
//經過反射完成了代理對象的建立
final Constructor<?> cons = cl.getConstructor(constructorParams);
return newInstance(cons, h);
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString());
}
}
複製代碼
參數說明:code
(1)定義動態代理類
public class ActorProxy implements InvocationHandler {
private Play player;
public ActorProxy(Play player){
this.player = player;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//處理被代理對象的方法實現
if ("show".equals(method.getName())){
System.out.println("代理處理show....");
return method.invoke(player, null);
}else if ("sing".equals(method.getName())){
System.out.println("代理處理sing....");
return method.invoke(player, 2);
}
return null;
}
}
複製代碼
代理類實現InvocationHandler接口,在invoke方法中對player(被代理對象)作相應的邏輯處理。
(2)使用
public class ProxyTest {
public static void main(String[] args) {
Play actor = new Actor();
//經過調用Proxy.newProxyInstance方法生成代理對象
Play proxy = (Play) Proxy.newProxyInstance(actor.getClass().getClassLoader()
, actor.getClass().getInterfaces(), new ActorProxy(actor));
//調用代理類相關方法
proxy.show();
proxy.sing(3);
}
}
複製代碼
(1)Retrofit使用:
定義接口
public interface MyService {
@GET("users/{user}/list")
Call<String> getMyList(@Path("user") String user);
}
複製代碼
新建retrofit對象,而後產生一個接口對象,而後調用具體方法去完成請求。
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://xxx.com")
.build();
MyService myService = retrofit.create(MyService.class);
Call<String> myList = myService.getMyList("my");
複製代碼
retrofit.create方法就是經過動態代理的方式傳入一個接口,返回了一個對象
(2)動態代理分析:
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();
private final Object[] emptyArgs = new Object[0];
@Override public Object invoke(Object proxy, Method method, @Nullable 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
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
複製代碼
經過Proxy.newProxyInstance,該動態代理對象能夠拿到請求接口實例上全部註解,而後經過代理對象進行網絡請求。
遠程代理:爲某個對象在不一樣的內存地址空間提供局部的代理對象
(1)AMS、ApplicationThread
(2)Binder模型
在插件化中,例如VirtualApk,hook住AMS的本地代理對象IActivityManager,至關於IActivityManager的一個代理,控制了IActivityManager的某些行爲
(1)建立動態代理
protected void hookSystemServices() {
try {
Singleton<IActivityManager> defaultSingleton;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
defaultSingleton = Reflector.on(ActivityManager.class).field("IActivityManagerSingleton").get();
} else {
defaultSingleton = Reflector.on(ActivityManagerNative.class).field("gDefault").get();
}
IActivityManager origin = defaultSingleton.get();
//建立動態代理對象ActivityManagerProxy
IActivityManager activityManagerProxy = (IActivityManager) Proxy.newProxyInstance(mContext.getClassLoader(), new Class[] { IActivityManager.class },
createActivityManagerProxy(origin));
// 經過反射Hook住了IActivityManager
Reflector.with(defaultSingleton).field("mInstance").set(activityManagerProxy);
if (defaultSingleton.get() == activityManagerProxy) {
this.mActivityManager = activityManagerProxy;
Log.d(TAG, "hookSystemServices succeed : " + mActivityManager);
}
} catch (Exception e) {
Log.w(TAG, e);
}
}
protected ActivityManagerProxy createActivityManagerProxy(IActivityManager origin) throws Exception {
return new ActivityManagerProxy(this, origin);
}
複製代碼
建立動態代理ActivityManagerProxy,並經過反射對IActivityManager進行hook
(2)動態代理對象
public class ActivityManagerProxy implements InvocationHandler {
......
//被代理對象
private IActivityManager mActivityManager;
public ActivityManagerProxy(PluginManager pluginManager, IActivityManager activityManager) {
this.mPluginManager = pluginManager;
this.mActivityManager = activityManager;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//經過監聽被代理對象的某些方法,執行本身的相關邏輯
if ("startService".equals(method.getName())) {
try {
return startService(proxy, method, args);
} catch (Throwable e) {
Log.e(TAG, "Start service error", e);
}
}
......
}
}
複製代碼
ActivityManagerProxy實現InvocationHandler,並持有了IActivityManager,在IActivityManager方法執行時,進行控制並執行本身的相應邏輯