一、概述
前两节接连介绍了,Java的反射技术,以及把Java的反射技术封装成类库。本节接下来介绍的内容都是基于以上两节来实现的。如果读者看起来吃力可以回过头看看前两节的内容,然后接着看本节内容。
二、实战
整体流程描述:首先先定义一个泛型的单例类Singleton,然后在BookManger中实例化这个单例。IBook是一个接口。JavaBook和AndroidBook是IBook的具体实现类。ReflectUtil是反射工具类
在BookManger中默认单例返回的是JavaBook。我们通过反射将其动态替换为默认返回AndroidBook。
1.IBook.java
package com.yw.reflectjavalib.generic; /** * book接口 * create by yangwei * on 2020-02-07 16:59 */ public interface IBook { void write(); void read(); }
2.JavaBook.java
package com.yw.reflectjavalib.generic; /** * create by yangwei * on 2020-02-07 17:04 */ public class JavaBook implements IBook { @Override public void write() { System.out.println("正在写java代码"); } @Override public void read() { System.out.println("正在读java代码"); } }
3.AndroidBook.java
package com.yw.reflectjavalib.generic; import com.yw.reflectjavalib.LogUtil; /** * create by yangwei * on 2020-02-07 17:07 */ public class AndroidBook implements IBook { @Override public void write() { LogUtil.e("正在写Android"); } @Override public void read() { LogUtil.e("正在阅读Android"); } }
4.BookManger
package com.yw.reflectjavalib.generic; /** * book的管理类 * create by yangwei * on 2020-02-07 17:03 */ public class BookManager { private static final Singleton<IBook> getDefault = new Singleton<IBook>() { @Override protected IBook create() { return new JavaBook(); } }; public static IBook getDefault() { return getDefault.get(); } }
5.Singleton
package com.yw.reflectjavalib.generic; /** * 泛型单例 * create by yangwei * on 2020-02-07 17:00 */ public abstract class Singleton<T> { private T mInstance; protected abstract T create(); public final T get() { synchronized (this) { if (mInstance == null) { mInstance = create(); } } return mInstance; } }
6.ReflectGenericDemo
package com.yw.reflectjavalib.generic; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Proxy; /** * 对泛型进行反射 * <p> * 通过动态代理模式+反射把JavaBook替换成我们需要的AndroidBook。对BookManager进行代码注入 * create by yangwei * on 2020-02-07 16:58 */ public class ReflectGenericDemo { public static void main(String[] args) throws Exception { //获取Singleton的mInstance字段 Class<?> singleton = Class.forName("com.yw.reflectjavalib.generic.Singleton"); Field mInstanceField = singleton.getDeclaredField("mInstance"); mInstanceField.setAccessible(true); //获取bookmanager的getDefault字段 Class<?> bookManager = Class.forName("com.yw.reflectjavalib.generic.BookManager"); Field getDefaultField = bookManager.getDeclaredField("getDefault"); getDefaultField.setAccessible(true); //获取gedefault字段的值,其实就是Singleton实例 Object getDefault = getDefaultField.get(null); //把JavaBook替换为AndroidBook mInstanceField.set(getDefault,new AndroidBook()); BookManager.getDefault().read(); } }
运行BookManger.getDefault().read()方法,我们发现打印出来的确实是“正在阅读Android”,如果把mInstanceFiled.set(getDefault,new AndroidBook)注释掉,则输出的是“正在阅读Java”。这种情况也可称之为Hook,利用这种技术我们可以做一些底层类的替换(android插件化相关)。例如:我们可以对AMS和PMS进行hook。或者对Instrumentation或者mCallback进行hook。
下一节将讲解动态代理,也是基于反射,比这一节的内容更为高级一点。一遍我们在做插件话hook的时候通常会用到proxy.newProxyInstance.敬请期待