arouter-api version : 1.4.1
preface
So far, ARouter has not resolved the final dependency injection, so today we will explore its implementation principle.
PS: because the principle of dependency injection is relatively simple, this article will be short.
@Autowired parsing
To implement dependency injection with ARouter, you need to add
copyARouter.getInstance().inject(this);
Then our code becomes the entry point for our analysis.
copypublic void inject(Object thiz) { _ARouter.inject(thiz); }
ARouter is still called internally_ The inject method of ARouter.
copystatic void inject(Object thiz) { AutowiredService autowiredService = ((AutowiredService) ARouter.getInstance().build("/arouter/service/autowired").navigation()); // If autowiredService is not empty, complete dependency injection if (null != autowiredService) { autowiredService.autowire(thiz); } }
It is found that dependency injection is very similar to interceptors, which are completed by using service components. The service component of dependency injection is called AutowiredService. Tracing shows that its implementation class is AutowiredServiceImpl.
copy@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 { // If the instance class is blacklisted, dependency injection will not be completed if (!blackList.contains(className)) { // Get from cache first ISyringe autowiredHelper = classCache.get(className); // Create object without cache if (null == autowiredHelper) { // No cache. autowiredHelper = (ISyringe) Class.forName(instance.getClass().getName() + SUFFIX_AUTOWIRED).getConstructor().newInstance(); } // Complete dependency injection autowiredHelper.inject(instance); // Put in cache classCache.put(className, autowiredHelper); } } catch (Exception ex) { // Add to the blacklist if there is an error blackList.add(className); // This instance need not autowired. } } }
ISyringe is the interface extracted by dependency injection,
copypublic interface ISyringe { void inject(Object target); }
So who is the implementation class of ISyringe? The answer is the class XXXX automatically generated at compile time
ARouterAutowired, let's find the Test1Activity generated in the demo
ARouterAutowired take a look
copypublic 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); } }
From the automatically generated code above, we can see that dependency injection actually uses getintent internally Getxxxextra (similarly, Fragment uses getarguments () getXxx() ). It should be noted that the field modified by @Autowired cannot be private, otherwise an error will be reported when automatically generating code.
In addition, what is a SerializationService used for in the above code? In fact, SerializationService is used for json serialization. In the demo, an implementation class JsonServiceImpl is officially given, and Alibaba's fastjson is used internally. If you need to customize children's shoes, you can refer to JsonServiceImpl to implement it yourself.
end
Seeing this, basically, we have finished talking about ARouter dependency injection.
In this series, the process of ARouter code level is almost the same. The remaining two parts are gradle plugin and compiler, which have not been parsed yet. I will tell you later.
bye bye