arouter-api version : 1.4.1
前言
到現(xiàn)在為止,ARouter 還有最后的依賴注入還沒有解析過斟冕,那么今天就來深入探究一下其實現(xiàn)原理。
PS : 因為依賴注入的原理還比較簡單缅阳,所以本篇篇幅會較短磕蛇。
@Autowired解析
想要用 ARouter 實現(xiàn)依賴注入,需要在 Activity/Fragment 中加上
ARouter.getInstance().inject(this);
那么我們這個代碼就成為了我們分析的入口了十办。
public void inject(Object thiz) {
_ARouter.inject(thiz);
}
ARouter 內(nèi)部還是調(diào)用了 _ARouter 的 inject 方法秀撇。
static void inject(Object thiz) {
AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation());
// 如果 autowiredService 不為空,完成依賴注入
if (null != autowiredService) {
autowiredService.autowire(thiz);
}
}
發(fā)現(xiàn)依賴注入和攔截器很相似向族,都是利用服務組件來完成的呵燕。依賴注入的服務組件叫 AutowiredService ,跟蹤可以發(fā)現(xiàn)件相,它的實現(xiàn)類是 AutowiredServiceImpl 再扭。
@Route(path = "/arouter/service/autowired")
public class AutowiredServiceImpl implements AutowiredService {
private LruCache<String, ISyringe> classCache;
private List<String> blackList;
@Override
public void init(Context context) {
classCache = new LruCache<>(66);
blackList = new ArrayList<>();
}
@Override
public void autowire(Object instance) {
String className = instance.getClass().getName();
try {
// 如果 instance 這個類進入黑名單了燕酷,就不會完成依賴注入
if (!blackList.contains(className)) {
// 先從緩存中取
ISyringe autowiredHelper = classCache.get(className);
// 沒有緩存就創(chuàng)建對象
if (null == autowiredHelper) { // No cache.
autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance();
}
// 完成依賴注入
autowiredHelper.inject(instance);
// 放入緩存中
classCache.put(className, autowiredHelper);
}
} catch (Exception ex) {
// 出錯就加入黑名單中
blackList.add(className); // This instance need not autowired.
}
}
}
其中 ISyringe 就是依賴注入抽取出來的接口衡便,
public interface ISyringe {
void inject(Object target);
}
那么 ISyringe 的實現(xiàn)類又是誰呢贷掖?答案就是在編譯期自動生成的類 XXXX$$ARouter$$Autowired
乔外,我們找 demo 中生成的 Test1Activity$$ARouter$$Autowired
來看看
public class Test1Activity$$ARouter$$Autowired implements ISyringe {
private SerializationService serializationService;
@Override
public void inject(Object target) {
serializationService = ARouter.getInstance().navigation(SerializationService.class);
Test1Activity substitute = (Test1Activity)target;
substitute.name = substitute.getIntent().getStringExtra("name");
substitute.age = substitute.getIntent().getIntExtra("age", substitute.age);
substitute.height = substitute.getIntent().getIntExtra("height", substitute.height);
substitute.girl = substitute.getIntent().getBooleanExtra("boy", substitute.girl);
substitute.ch = substitute.getIntent().getCharExtra("ch", substitute.ch);
substitute.fl = substitute.getIntent().getFloatExtra("fl", substitute.fl);
substitute.dou = substitute.getIntent().getDoubleExtra("dou", substitute.dou);
substitute.ser = (com.alibaba.android.arouter.demo.testinject.TestSerializable) substitute.getIntent().getSerializableExtra("ser");
substitute.pac = substitute.getIntent().getParcelableExtra("pac");
if (null != serializationService) {
substitute.obj = serializationService.parseObject(substitute.getIntent().getStringExtra("obj"), new com.alibaba.android.arouter.facade.model.TypeWrapper<TestObj>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'obj' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!");
}
if (null != serializationService) {
substitute.objList = serializationService.parseObject(substitute.getIntent().getStringExtra("objList"), new com.alibaba.android.arouter.facade.model.TypeWrapper<List<TestObj>>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'objList' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!");
}
if (null != serializationService) {
substitute.map = serializationService.parseObject(substitute.getIntent().getStringExtra("map"), new com.alibaba.android.arouter.facade.model.TypeWrapper<Map<String, List<TestObj>>>(){}.getType());
} else {
Log.e("ARouter::", "You want automatic inject the field 'map' in class 'Test1Activity' , then you should implement 'SerializationService' to support object auto inject!");
}
substitute.url = substitute.getIntent().getStringExtra("url");
substitute.helloService = ARouter.getInstance().navigation(HelloService.class);
}
}
從上面自動生成的代碼中看出來渊迁,依賴注入實際上內(nèi)部還是使用 getIntent.getXxxExtra
的形式來賦值的(同理钱骂,F(xiàn)ragment 用的是getArguments().getXxx()
)屋厘。需要注意的是紧索,@Autowired 修飾的字段不能是 private 的,不然在自動生成代碼的時候會報錯区赵。
另外惭缰,上面的代碼中有一個 SerializationService 是用來干什么的?其實 SerializationService 是 json 序列化用的笼才。在 demo 中官方給出了一個實現(xiàn)類 JsonServiceImpl 漱受,內(nèi)部用的是阿里的 fastjson 。如果有需要自定義的童鞋患整,可以參照著 JsonServiceImpl 自己去實現(xiàn)拜效。
結束
看到這,基本上 ARouter 依賴注入的東西就講完了各谚。
這一系列下來紧憾,ARouter 代碼層面的流程都講的差不多。剩下就是 gradle-plugin 和 compiler 這兩個部分還沒解析過昌渤,等時間了再給大家講赴穗。
bye bye